import angr
# import autoblob
import os
import sys
import angr.analyses.reaching_definitions.dep_graph as dep_graph

import threading
from angr.calling_conventions import SimCC
from angr.engines.light import SpOffset, RegisterOffset
from angr.knowledge_plugins.key_definitions.atoms import Register, SpOffset, MemoryLocation
from angr.knowledge_plugins.key_definitions.undefined import Undefined
from angr.knowledge_plugins.key_definitions.definition import Tag
from angr.knowledge_plugins.key_definitions.tag import ReturnValueTag
from angr.knowledge_plugins.key_definitions.tag import ParameterTag,InitialValueTag
from angr.knowledge_plugins.key_definitions.live_definitions import Definition
from typing import TYPE_CHECKING, List, Set, Optional, Tuple
from networkx.drawing.nx_agraph import write_dot
import claripy
import re
import pickle
# from angr.analyses.reaching_definitions.external_codeloc import ExternalCodeLocation
global_counter=[0]

import time
import datetime
def extract_attributes(obj) -> dict:
    """
    递归提取对象的所有可序列化属性。
    """
    if isinstance(obj, dict):
        return {k: extract_attributes(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [extract_attributes(v) for v in obj]
    elif hasattr(obj, "__dict__"):  # 提取对象的所有可用属性
        return {k: extract_attributes(v) for k, v in obj.__dict__.items() if not k.startswith("_")}
    else:
        return obj

def save_blk_and_definitions_to_json(blk, collect_definatins, filename="blk_data.json"):
    """
    将 blk 和 collect_definatins 数据存入 JSON 文件。
    """
    data = {
        "blk": extract_attributes(blk),
        "collect_definitions": [extract_attributes(d) for d in collect_definatins]
    }
    
    with open(filename, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=4, ensure_ascii=False)

    print(f"数据已成功保存到 {filename}")

SOURCES = ["sub_1d170","config_get","NK_query_entry_get","webGetVarString","bcm_nvram_get","GetValue","acosNvramConfig_read","sub_42af24",'sub_42a978',
           'get_cgi',"websGetVar",'nvram_get', 'nvram_safe_get', 'nvram_default_get', 'getenv',  'nvram_pf_get', 'acosNvramConfig_get', 'config_get',
             'uciGet', 'entry',  'wpa_config_get',  'httpGenListDataGet',  'cJSON_GetArrayItem', 'wpa_config_set', 'vici_find_str', 'DoHardwareComponent', 
               'device_get_string_value', 'cJSON_Parse', 'uciSet', 'OM_ValGet', 'acosUciConfig_get',  'CAL_abstract_get',  'json_object_object_get',
                 "json_object_object_get_ex", 'json_tokener_parse',  'OM_ValFind', 'get_parameter', 'get_wlan_setting', 'av_dict_get', 'cgi_value', 
                   'stringOut',  'cJSON_GetObjectItem', 'sw_getValueByName', 'querystr', 'find_val', 'log_query',  'value_parser_by_index_D7000', 
                   'getoption', 'WEB_GetVar',  'av_opt_get', 'paramValueFromObjGet',  'help_getObjPtr',  'NCONF_get_string', 'av_metadata_get',  'httpGetEnv',"gets",
                    "recvfrom", "recvmsg", "recvmsg","my_fgets"]


transitive_set=["config_set","SetValue",'setenv', 'nvram_set', 'nvram_safe_set', 'nvram_pf_set', 'artblock_set',  'acos_nvram_set', 'acosNvramConfig_set',
 'acosNvramConfig_write', 'envz_add', 'config_set', 'uciSet', 'device_set_string_value', 'wpa_config_set', 'scfgmgr_set_by_index_D7000',
 'acosUciConfig_set', 'OM_ValSet', 'CAL_abstract_set']


SINKS = ['strcpy','strcat','sprintf','system', '___system', "_system",'bstar_system', 'popen', 'doSystemCmd', 'doShell', 'twsystem', 'CsteSystem', 'cgi_deal_popen', 'ExecShell', 'exec_shell_popen', 'exec_shell_popen_str','wl_exec_cmd','execve', "execl", "_eval", "eval", "sh", "send", "execlp","doSystem","sprintf","memcpy"] 

# to collect user defined functions
New_input_getters=[]
STACK=[]
Analyzed_Before={}  # to store previously analysed function decopiler to save time of regenerate them

import os
from functools import reduce

import ailment
from angr import Project
from angr.analyses.reaching_definitions.dep_graph import DepGraph
from angr.code_location import CodeLocation
from angr.knowledge_plugins.key_definitions.atoms import Atom
from angr.procedures.definitions.glibc import _libc_decls



from angr.analyses.reaching_definitions.function_handler import FunctionHandler
from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE, OP_AFTER

from angr.knowledge_plugins.key_definitions.tag import LocalVariableTag, ParameterTag, ReturnValueTag, Tag, \
    SideEffectTag
from angr.knowledge_plugins.key_definitions.atoms import Atom, Register, MemoryLocation, Tmp
from angr.engines.light import SimEngineLight, SpOffset, RegisterOffset
# from angr.knowledge_plugins.key_definitions.dataset import DataSet
from angr.knowledge_plugins.key_definitions.unknown_size import UnknownSize, UNKNOWN_SIZE

from angr.calling_conventions import SimRegArg
# from ...storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues

import re
import pickle
import json
from random import shuffle
import networkx as nx
#from angr.angrdb.db import AngrDB
#from angr.angrdb.serializers.variables import VariableManagerSerializer
# This is part of ongoing research and cannot be released at the moment :'(
# from argument_resolver.handlers import handler_factory
#from utils import Utils

# Ugly hack (part I):
# Because `angr` does not yet support storing some information we need in the RDA's state;
# We will store it globally to have access to it during the script execution.
# Make it a dictionary of `Definition` -> `List[MemoryLocation]` (there could be several calls to `strcpy`,
# several source definitions, and all might have different stack portions to overwrite!).
# def save_json(data, filename):
#     with open(filename, 'w') as f:
#         json.dump(data, f, indent=4)
import string
import binascii
def get_bin_strings(filename):
    with open(filename, "rb") as f:
        results = []
        last_off = None
        off = 0
        tp_str = ""

        for xx in f.read():
            c=chr(xx)
            try:
                if c in string.printable and c != '\n':
                    last_off = off if not last_off else last_off
                    tp_str += c
                else:
                    if tp_str and len(tp_str) > 1:
                        results.append((tp_str, last_off))
                    last_off = None
                    tp_str = ""
            except Exception as e:
                ssss=0
            off += 1

    return results



def get_indirect_str_refs(p, cfg, str_addrs):
    ret = []

    # FIXME: (DEPRECATED?)
    # code reference
    code_refs = [s for s in cfg.memory_data.items() if 'code reference' in str(s)]
    for a, ref in code_refs:
        addr = ref.address
        cnt = p.loader.memory.read_bytes(addr, p.arch.bytes)

        if 'LE' in p.arch.memory_endness:
            cnt = reversed(cnt)

        cnt = binascii.hexlify(bytearray(cnt))
        if int(cnt, 16) in str_addrs:
            ret += [s for s in cfg.memory_data.items() if s[0] == addr]

    # pointers
    refs = [s for s in cfg.memory_data.items() if s[0] in str_addrs]
    for ref in refs:
        cnt = ref[1]
        if hasattr(cnt, 'pointer_addr'):
            pt = cnt.pointer_addr
            ret += [s for s in cfg.memory_data.items() if s[0] == pt]

    refs = [s for s in cfg.memory_data.items() if s[0] in str_addrs]
    for ref in refs:
        cnt = ref[1]
        if hasattr(cnt, 'pointer_addr'):
            pt = cnt.pointer_addr
            # we collect both references
            ret += [(s.address, s) for k, s in cfg.insn_addr_to_memory_data.items() if s.address == pt]
            ret += [(ind_addr, s) for k, s in cfg.insn_addr_to_memory_data.items() if s.address == pt for ind_addr in str_addrs]

    return ret

defination_dictionary=[] # to save temporary definations

OVERWRITTEN_STACK_VARIABLES = {}

strcpy_counter = [0]
strchr_counter = [0]
getenv_counter = [0]
init_addr_conter=[0]


def plot_defiantion(d0,state):
    write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
    os.system("dot -Tsvg -o ss.svg zz.dot")
    
#### for sanitization check

def get_clinic_block(project,clinic, addr):
        #'''
        blk=None
        if not clinic is  None :
            for block in clinic.graph.nodes():
                if block.addr == addr:
                    blk= block
                    #return blk
                    break
            

            #'''
            try :
                if blk is not None and  hasattr(blk,"statements") and len(blk.statements) >0 :
                    return blk
            except Exception as e:
                pass
            #'''
            
            
                
        
        
        
        
        try:
            # project=self._analysis.project
            manager = ailment.Manager(arch=project.arch)
            block = project.factory.block(addr)
            ail_block = ailment.IRSBConverter.convert(block.vex, manager)
            simp = project.analyses.AILBlockSimplifier(ail_block,  clinic.function.addr)
            csm = project.analyses.AILCallSiteMaker(simp.result_block)
            if csm.result_block:
                ail_block = csm.result_block
                simp = project.analyses.AILBlockSimplifier(ail_block,  clinic.function.addr)
            return simp.result_block
        except Exception as e :
            #print(block.pp())
            return None    




def get_strings(d0,cfg,rd_ddg_graph):
        b0 = "not_static_string"
        pcd0 = [d for d in rd_ddg_graph.predecessors(d0)]
        memory_def_flag = False
        for df in pcd0:
            if type(df.atom) == MemoryLocation and df.atom.addr in cfg.memory_data:
                memory_def_flag = True
        if not memory_def_flag:
            extended_defs = []
            for df in pcd0:
                extended_defs.extend([d for d in rd_ddg_graph.predecessors(df)])
            pcd0 = extended_defs

        string_list = []
        for df in pcd0:
            if type(df.atom) == MemoryLocation and df.atom.addr in cfg.memory_data and cfg.memory_data[
                df.atom.addr].content is not None:
                bb0 = cfg.memory_data[df.atom.addr]
                if bb0.content is not None:
                    # b0=str(bb0.content)[2:-1]
                    i = 0
                    while str(cfg.project.loader.memory.load(bb0.addr, bb0.size + i))[bb0.size + i + 1] != '\\':
                        i += 1
                    b0 = str(cfg.project.loader.memory.load(bb0.addr, bb0.size + i - 1))[2:-1]
                    string_list.append(b0)
        if len(string_list) > 1:
            b0 = "#".join(string_list)
            
        return b0

class MyHandler(FunctionHandler):
    def __init__(self):
        self._analysis = None

    def hook(self, rda):
        self._analysis = rda
        return self
    
    def set_start_function(self,start_function) :
        self.start_function=start_function
        
    def set_call_graph(self,call_graph) :
        self.call_graph=call_graph
        
        
    
    def set_variable_manager(self, variable_manager):
        self.variable_manager = variable_manager

    def get_variable_manager(self):
        return self.variable_manager

    def set_cfg(self, cfg):
        self.cfg = cfg

    def get_cfg(self):
        return self.cfg
    
    
    def set_clinic(self, clinic):
        self.clinic = clinic

    def get_clinic(self):
        return self.clinic
    def set_dec(self,dec):
        self.dec=dec
        
    def get_dec(self):
        return self.dec
    
    def set_rd_on_clinic(self, rd_on_clinic):
        self.rd_on_clinic = rd_on_clinic

    def get_rd_on_clinic(self):
        return self.rd_on_clinic
    
    
    def set_vfg(self, vfg):
        self.vfg = vfg

    def get_vfg(self):
        return self.vfg
    
    def set_sptracker(self, sptracker):
        self.sptracker = sptracker

    def get_sptracker(self):
        return self.sptracker

    def set_current_fucntion(self, cur_fun):
        self.cur_fun = cur_fun

    def get_current_fucntion(self):
        return self.cur_fun

    def set_result_file(self, result_file):
        self.result_file = result_file

    def get_result_file(self):
        return self.result_file
    
    def set_get2set_file(self, get2set_file):
        self.get2set_file = get2set_file

    def get_get2set_file(self):
        return self.get2set_file
    
    def set_visited_file(self, visited_file):
        self.visited_file = visited_file

    def get_visited_file(self):
        return self.visited_file

    def set_ret_sites(self, ret_sites):
        self._ret_sites = ret_sites
        
        
    def get_stringby_use_def(self, reg_def,state):
        # Now we need to analyze the definition for this atom
        reg_seen_defs = set()
        defs_to_check = set()
        defs_to_check.add(reg_def)

        # Cache of all seen nodes (Tie the knot)
        seen_defs = set()
        bb=""
        while len(defs_to_check) != 0:
            current_def = defs_to_check.pop()
            seen_defs.add(current_def)
            # Check if the current Definition has a tag
            
            if type(current_def.atom)==MemoryLocation  and 'readonly' in  f'{current_def}' :
                i=0
                while str(self.cfg.project.loader.memory.load(current_def.atom.addr, i+1))[i+1] != '\\':
                     i+=1
                bb=str(self.cfg.project.loader.memory.load(current_def.atom.addr, i-1))[2:-1]
                if len(bb)>2:
                    break
            
            else:

                # If we have undefined pointers (a.k.a. Top value) we need to process the predecessors.
                if current_def in state.dep_graph.graph.nodes():
                    for pred in state.dep_graph.graph.predecessors(current_def):
                        if pred not in seen_defs:
                            defs_to_check.add(pred)

        return bb
    
    
    
    
    def is_defination_tainted(self, d0,function,state):
        
            is_tainted=False
            def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
            def_explorer.set_current_state(state)
            def_explorer.set_current_codeloc(state.current_codeloc)
            def_explorer.set_RDA_handler(self)
            def_explorer.set_current_fucntion(self.cur_fun)
           
            reg_seen_defs,Paths,visited_functions=backtrack_definations(def_explorer, reg_defs=[d0], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr, check_is_tainted_def=True)
                
            for overall_def, path,visited_function in zip(reg_seen_defs,Paths,visited_functions) :
                if overall_def[0] == "get2set" or (overall_def[0] == "retval" and overall_def[1] != None ) :
                    is_tainted=True
                    break
                
            return is_tainted
                    
        
    
    def get_memoryDef_by_use_def(self, reg_def,state):
        # Now we need to analyze the definition for this atom
        reg_seen_defs = set()
        defs_to_check = set()
        defs_to_check.add(reg_def)

        # Cache of all seen nodes (Tie the knot)
        seen_defs = set()
        while len(defs_to_check) != 0:
            current_def = defs_to_check.pop()
            seen_defs.add(current_def)            
            if type(current_def.atom)==MemoryLocation  and 'stack' in  f'{current_def}' :
                return current_def                           
            else:
                if current_def in state.dep_graph.graph.nodes():
                    preds= [d for d in state.dep_graph.graph.predecessors(current_def) ]
                    if type(current_def.atom) == Register and len(preds)==1:
                        for pred in preds:
                            if pred not in seen_defs:
                                defs_to_check.add(pred) 

        return None
    
    
    
    def get_functionAddress_by_use_def(self, reg_def,state):
        # Now we need to analyze the definition for this atom
        functions=[]
        reg_seen_defs = set()
        defs_to_check = set()
        defs_to_check.add(reg_def)

        # Cache of all seen nodes (Tie the knot)
        seen_defs = set()
        while len(defs_to_check) != 0:
            current_def = defs_to_check.pop()
            seen_defs.add(current_def)            
            #print(current_def)
            #import ipdb;
            #ipdb.set_trace()
            #pass
            if type(current_def.atom)==MemoryLocation and current_def.atom.size is None and 'readonly' in  f'{current_def}' :
                try:
                    addr= current_def.atom.addr      
                    func=self.cfg.functions.get_by_addr(addr)
                    if func is not None:
                        functions.append(func)
                except Exception as e:
                    print("error at 441 ", e)    
                    continue
            else:
                if current_def in state.dep_graph.graph.nodes():
                    preds= [d for d in state.dep_graph.graph.predecessors(current_def) ]                    
                    for pred in preds:
                        if pred not in seen_defs:
                            defs_to_check.add(pred) 

        return functions
        
     

    def get_def_from_parameter(self, function, parameter_position, state,blk=None):
        flag=True
        # try:
        #     cc = function.calling_convention

        #     parameter_atom = Atom.from_argument(
        #         SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
        #         self._analysis.project.arch.registers
        #     )
        # except Exception as e :
        #     print("error at 465 ", e)
        #     flag=True
        
        print("parameter_position=",parameter_position)
        try:
            if flag and "MIPS" in state.arch.name:
                ARG_REGS=["a0","a1","a2",'a3']
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                '''
                if  parameter_position in range(4):
                    oprand=state.arch.registers[ ARG_REGS[parameter_position]  ]
                    parameter_atom=Register(oprand[0],oprand[1])
                    
                elif blk is not None and   hasattr(blk,"statements") and len(blk.statements) >0  and  type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >0:
                    oprand=blk.statements[-1].args[parameter_position]#.reg_offset
                    parameter_atom=Register(oprand.reg_offset,oprand.size)
                '''    
                if parameter_position==0 :
                    parameter_atom=Register(24,4)
                elif parameter_position==1 :
                    parameter_atom=Register(28,4)
                elif parameter_position==2 :
                    parameter_atom=Register(32,4)
                elif parameter_position==3 :
                    parameter_atom=Register(36,4)
                '''
                
            elif flag and "ARM" in state.arch.name: #ARM
                try:
                    ARG_REGS=["r0","r1","r2",'r3']
                    if  parameter_position in range(4):
                        oprand=state.arch.registers[ ARG_REGS[parameter_position]  ]
                        parameter_atom=parameter_atom=Register(oprand[0],oprand[1])#Register(oprand.reg_offset,oprand.size)#

                    elif blk is not None and   hasattr(blk,"statements") and len(blk.statements) >0  and  type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >0:
                        oprand=blk.statements[-1].args[parameter_position]#.reg_offset
                        parameter_atom=Register(oprand[0],oprand[1])
                except Exception as e:                    
                    #''' 
                    print("error at 505 ", e)
                    if parameter_position==0 :
                        parameter_atom=Register(8,4)
                    elif parameter_position==1 :
                        parameter_atom=Register(12,4)
                    elif parameter_position==2 :
                        parameter_atom=Register(16,4)
                    elif parameter_position==3 :
                        parameter_atom=Register(20,4)
                    elif blk is not None and   hasattr(blk,"statements") and len(blk.statements) >0  and  type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >0:
                        oprand=blk.statements[-1].args[parameter_position]#.reg_offset
                        parameter_atom=Register(oprand[0],oprand[1])
                    #'''
                
            def0 = state.get_definitions(parameter_atom)
            d0 = [d for d in def0][0]
        except Exception as e:
            d0=None
            
            size: int = state.arch.bits#state.arch.byte_width
            top = state.top(size * state.arch.byte_width)
            top = state.annotate_with_def(top, Definition(parameter_atom, state.current_codeloc))
            data: MultiValues  = MultiValues(top)
            mv=state.kill_and_add_definition(parameter_atom, state.current_codeloc, data)
            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
            ff=next( iter(ff_defs) )

            return ff
            #pass 
            #raise
            #pass
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''

        return d0
    
    
    def get_clinic_block(self,clinic, addr,flag=True):
        #'''
        blk=None
        if not clinic is  None  and flag:
            for block in clinic.graph.nodes():
                if block.addr == addr:
                    blk= block
                    break
            #return None
            #'''

            try :
                if blk is not None and  hasattr(blk,"statements") and len(blk.statements) >0  and  type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >0 :
                    return blk
            except Exception as e:
                pass
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                '''
        
        
        #print(block.vex.pp())
        
        try:
            
            project=self._analysis.project
            manager = ailment.Manager(arch=project.arch)
            block = project.factory.block(addr)
            ail_block = ailment.IRSBConverter.convert(block.vex, manager)
            simp = project.analyses.AILBlockSimplifier(ail_block,  self.cur_fun.addr)
            csm = project.analyses.AILCallSiteMaker(simp.result_block)
            if csm.result_block:
                ail_block = csm.result_block
                simp = project.analyses.AILBlockSimplifier(ail_block,  self.cur_fun.addr)
            return simp.result_block
        except Exception as e :
            return None
        
        
        


    
    def _state_from(self, rda, exit_site_addresses):
        assert len(exit_site_addresses) > 0, 'Assuming there is at least one return site'

        exit_states = list(map(
            lambda site_address: rda.observed_results[('node', site_address, OP_BEFORE)],
            exit_site_addresses
        ))  # insn

        # this to handle x86 when the functions implements stack protection
        # '''

        return_register_size = rda.project.arch.bytes  # 4 for MIPS, 8 for x86
        # rda.project.arch.name.startswith('MIPS')

        '''
        if len(exit_states)==1:
            #exit_states[0].getdefinations(Register(16,size=8, arch=rda.arch))

            def_2a = exit_states[0].get_definitions(Register(24,return_register_size))
            ff= [d for d in def_2a][0]
            #exit_states[0] = rda.observed_results[('insn', ff.codeloc.ins_addr, OP_AFTER)]
        '''

        first_state = exit_states[0]
        
        try:
            if len(exit_site_addresses) > 1:
                return reduce(
                    lambda acc, state: acc.merge(state),
                    exit_states,
                    first_state.copy(),
                )
            else:
                return first_state
        except Exception as e:
            return first_state
        
        
    def get_memory_defination(self,d0,function,state,codeloc,defination_only=False, defination_location=0,blk=None):
        #blk=self.get_clinic_block(self.clinic,d0.codeloc.block_addr)
        if blk is None:
            blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        
        atom= d0.atom
        ## atom will be modified if some conditions are stisified
        if blk is not None and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            
            
            if type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) > defination_location :
                arg0=call_statement.args[defination_location] 
                           
                if  type(arg0) == ailment.expression.Const and hasattr(arg0,"value")  :
                    ff= None
                    ff_list=[]
                    for node in state.dep_graph.nodes():
                        if isinstance(node.atom, MemoryLocation) and node.atom.addr==arg0.value:
                            if node not in ff_list:
                                ff_list.append(node)
                            ff= node
                            #print(node)
                            #print(" \n #### \n  #######\n")
                            #break
                            
                    
                    
                    
                    # if 1==0 and  abs( state.current_codeloc.ins_addr- int(0x823f8) )<=8:#strcpy_counter[0]==2:          0x82494
                    #     rrrrr=0

                    #     #write_dot(state.dep_graph.transitive_closure(d1), "zz.dot")
                    #     #os.system(f'dot -Tsvg -o {strcpy_counter[0]}_strcpy.svg zz.dot')
                    #     #'''
                    #     import ipdb;
                    #     ipdb.set_trace()
                    #     pass
                        #'''
                    
                    
                    
                    
                    
                    # incase there is more than global variable with same address but with different size,
                    # in this case we will select only the defination that we have a path
                    if len(ff_list)>1:
                                pred=[d for d in state.dep_graph.predecessors(d0)]
                                if len(pred)==1 and type(pred[0].atom)!=Register: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                                    pred=[d for d in state.dep_graph.predecessors(pred[0])]
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation :
                                            for GF in ff_list:
                                                if GF.atom.addr==  defination.atom.addr and defination.size ==GF.size:
                                                    ff=GF
                                                    break
                                else:
                                    for defination in pred :
                                        for GF in ff_list:
                                            if type(defination.atom)==MemoryLocation and GF.atom.addr==  defination.atom.addr and defination.size ==GF.size:
                                                ff=GF
                                                break
                        
                        
                    
                    
                        
                    if ff is not None :
                        if defination_only:
                            print("we are return ff only")
                            return ff
                        else:
                            try:
                                tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                                data: MultiValues = state.memory_definitions.load(ff.atom.addr, size=ff.atom.size)
                                mv = state.kill_and_add_definition(ff.atom, state.current_codeloc, data, tags=tags) # .block_addr
                                ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                                #ff = [d for d in ff_defs][0]
                                ff=next( iter(ff_defs) )
                            except Exception as e:
                                print("we could not update the golbal varaible, we just return its current defination. this should be fixed")
                            return ff
                       
                    
                    if 1==0 and ff is None and bb=="RoutingList":
                        import ipdb;
                        ipdb.set_trace()
                        pass 
                    #if function.name=="strstr":
                    #    print("man you are  filed")
                    if ff  is None:
                        print( " could not find the public varabile in graph")
                        
                        block_addr=blk.addr
                        project=self._analysis.project
                        manager = ailment.Manager(arch=project.arch)
                        block = project.factory.block(block_addr)

                        for stmt in block.vex.statements:
                            if hasattr(stmt,'offset') and state.arch.register_names[stmt.offset]==state.arch.register_names[d0.atom.reg_offset]:#'a1':
                                break
                        tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                        addr = arg0.value#self._expr(stmt.addr)
                        size = stmt.data.result_size(block.vex.tyenv) // 8
                        bits = stmt.data.result_size(block.vex.tyenv)
                        top = state.top(bits)
                        data = MultiValues(top)
                        temp_codeloc=CodeLocation(block.addr, stmt.tag_int, d0.codeloc.ins_addr,context=None,)
                        atom = MemoryLocation(arg0.value,size)
                        mv=state.kill_and_add_definition(atom, state.current_codeloc, data, tags=tags) #.block_addr
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        ff=next( iter(ff_defs) )
                        state.dep_graph.add_node(ff)
                        
                        pred=[d for d in state.dep_graph.predecessors(d0)]
                        if len(pred)>=1:
                            for defination in pred :
                                state.dep_graph.add_edge(ff,defination)
            
                        return ff
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            check_flag=False  # to check if we have catched expected conditions or not
            
            #Call (target: Load(addr=(0x5071e0<32> - 0x71b8<32>), size=4, endness=Iend_LE), prototype: None, args: None)
            # call_statement.target.addr is Sub(0x5071e0<32>, 0x71b8<32>)
            if type(blk.statements[-1]) == ailment.statement.Call and blk.statements[-1].args is None :
                    atom=d0.atom
                    #it need furthor investigation
                    check_flag=True
            
    
            elif type(blk.statements[-1]) == ailment.statement.Call and len(call_statement.args) >defination_location  :
                arg0=call_statement.args[defination_location] 
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    check_flag=True
                # arg0=s0
                elif hasattr(arg0,'reg_offset') :
                    reg=state.arch.registers[arg0.tags['reg_name']]
                    temp_def=next(iter(state.get_definitions(Register(reg[0],reg[1]))))
                    atom=temp_def.atom
                    check_flag=True
                # Call (target: 0x600354<32>, prototype: (char*, unsigned long (32 bits), char*, ...) -> int│ipdb>(32 bits), args: [Load(addr=stack_base-108, size=4, endness=Iend_LE), 0x8<32>, 0x4a48bc<3│ipdb>2>, s5<4>]) 
                #'''
                elif type(call_statement.args[0]) == ailment.expression.Load and  hasattr(call_statement.args[0],'addr') and type(call_statement.args[0].addr) == ailment.expression.StackBaseOffset :
                    atom=d0.atom
                    #it need furthor investigation
                    atom=MemoryLocation(SpOffset(state.arch.bits,call_statement.args[0].addr.offset),arg0.size)
                    check_flag=True
                # to handel this Load(addr=(s8<4> + 0x4cc<32>), size=4, endness=Iend_LE)    
                elif type(call_statement.args[0]) == ailment.expression.Load and  hasattr(call_statement.args[0],'addr') and type(call_statement.args[0].addr) == ailment.expression.BinaryOp and type(call_statement.args[0].addr.operands[1])==ailment.expression.Const:
                    atom=d0.atom
                    #it need furthor investigation
                    atom=MemoryLocation(SpOffset(state.arch.bits,call_statement.args[0].addr.operands[1].value),call_statement.args[0].addr.operands[1].size)
                    check_flag=True
                '''    
                elif type(call_statement.args[defination_location]) == ailment.expression.Load and type(call_statement.args[defination_location].addr) == ailment.expression.StackBaseOffset :
                    atom=d0.atom
                    #it need furthor investigation
                    #atom=MemoryLocation(SpOffset(state.arch.bits,arg0.addr),arg0.size)
                    check_flag=True
                
                '''    
                #'''
            
                 
            else:
                #arg0=call_statement.args[0]
                for smt in blk.statements :
                    if type(smt) == ailment.statement.Assignment and type(smt.src) == ailment.expression.StackBaseOffset and  smt.dst.tags['reg_name']==state.arch.register_names[d0.atom.reg_offset] :#'a0':
                        atom=MemoryLocation(SpOffset(state.arch.bits,smt.src.offset),smt.src.size)
                        check_flag=True
                        break
                    #elif type(smt) == ailment.statement.Store and len(blk.statements[-1].args) > defination_location and blk.statements[-1].args[defination_location]==stmt  :
                        
                
            
            
            
        try:
            if defination_only :
                return next(iter(state.get_definitions(atom)))
        except Exception as e :
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
            return d0
        
        
        tags = {LocalVariableTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}

       

        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)

        

        tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
        # state.add_use(atom, tmp_codeloc)
        mv = state.kill_and_add_definition(atom, tmp_codeloc, data, tags=tags)
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        #ff = [d for d in ff_defs][0]
        ff=next( iter(ff_defs) )
        
        return ff

    def handle_sprintf_xx(self, function, state, codeloc):  # , function):

        print('inside ',function.name)
        # function = project.kb.functions.function(name='sprintf')
        # function = self._analysis.project.kb.functions.function(codeloc.block_addr)
        
        extra_defination_flag=False

        cc = function.calling_convention

        parameter_position = 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        parameter_position_1 = 1
        parameter_atom_1 = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position_1], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        # in the future  we need to check if there is a third parameter or not
        parameter_position_2 = 2
        parameter_atom_2 = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position_2], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        if function.name in ["snprintf","vsnprintf"]:
            parameter_position_3 = 3
            parameter_atom_3 = Atom.from_argument(
                SimRegArg(cc.ARG_REGS[parameter_position_3], state.arch.bytes),
                self._analysis.project.arch.registers
            )

            def3 = state.get_definitions(parameter_atom_3)
            d3 = [d for d in def3][0]
            
        

        # d1 = state.register_definitions.load(parameter_atom.reg_offset, parameter_atom.size, endness=project.arch.register_endness)
        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]
        

        def1 = state.get_definitions(parameter_atom_1)
        d1 = [d for d in def1][0]

        def2 = state.get_definitions(parameter_atom_2)
        d2 = [d for d in def2][0]
                       

        # cd1 = d1.copy().pop()
        if d1 not in state.dep_graph.nodes():
            state.dep_graph.add_node(d1)
        if d2 not in state.dep_graph.nodes():
            state.dep_graph.add_node(d2)
        
        blk=self.get_clinic_block(self.clinic,d0.codeloc.block_addr)
        extrs_defination_location=0
        
        
        
        
        
        
        if function.name in  ["snprintf","vsnprintf"]:# "snprintf":
            extrs_defination_location=3
            dst_def = d3
            arg=blk.statements[-1].args[2]
            #bb=self.cfg.insn_addr_to_memory_data[d2.codeloc.ins_addr]
            #patttern=str(bb.content).split('%')
            
            try:
                #bb=self.cfg.insn_addr_to_memory_data[d2.codeloc.ins_addr]
                #patttern=str(bb.content).split('%')
                
                if d2.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                    bb1=self.cfg.insn_addr_to_memory_data[d2.codeloc.ins_addr]
                    i=0
                    while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                        i+=1
                    bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                    
                elif type(arg) ==ailment.expression.Const:
                    i=0
                    while not( str(self.cfg.project.loader.memory.load(arg.value, i))[i+1] == '\\' and str(self.cfg.project.loader.memory.load(arg.value, i))[i+2] == 'x'):
                          i+=1
                    bb=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                    
                    
                elif hasattr(arg,'reg_offset') :
                    for smt in blk.statements:
                        if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name'] == state.arch.register_names[d0.atom.reg_offset] and type(smt.src) == ailment.expression.Const:
                            i=0
                            while str(self.cfg.project.loader.memory.load(smt.src.value, i))[i+1] != '\\':
                                  i+=1
                            bb=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                            print("Did I arrived here")
                            break
                
                else:
                    bb=get_strings(d2,self.cfg,state.dep_graph)
        
                patttern=bb.split('%')
            except Exception as e:
                bb=""
                patttern=[]
                dst_def = d2
                d3=d2
            
                            
            
            
        else:
            extrs_defination_location=2
            dst_def = d2
            arg=blk.statements[-1].args[1]
            try:
                if d1.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                    bb1=self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr]
                    i=0
                    while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                        i+=1
                    bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                    
                 
                
                
                elif type(arg) ==ailment.expression.Const:
                    i=0
                    while not( str(self.cfg.project.loader.memory.load(arg.value, i))[i+1] == '\\' and str(self.cfg.project.loader.memory.load(arg.value, i))[i+2] == 'x'):
                          i+=1
                    bb=str(self.cfg.project.loader.memory.load(arg.value, i-1))[2:-1]
                    
                    
                elif hasattr(arg,'reg_offset') :
                    for smt in blk.statements:
                        if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name'] == state.arch.register_names[d0.atom.reg_offset] and type(smt.src) == ailment.expression.Const:
                            i=0
                            while str(self.cfg.project.loader.memory.load(smt.src.value, i))[i+1] != '\\':
                                  i+=1
                            bb=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                            print("Did I arrived here")
                            break
                
                
                else:
                    bb=get_strings(d2,self.cfg,state.dep_graph)
        
                patttern=bb.split('%')
                
            except Exception as e:
                bb=""
                patttern=[]
                dst_def = d1
                d2=d1
                '''
                print(e)
                import ipdb;
                ipdb.set_trace()
                pass
                '''
                
        
        #if d1 not in state.dep_graph.nodes():
        #    state.dep_graph.add_node(d1)
            
        ##ff=get_memory_defination(d0,function,state,codeloc)

        # magic_graph_print(state.dep_graph.transitive_closure(d0))
        
       
        try:
            if 1==0 and hasattr(blk,"statements") and len(blk.statements) >0 and self.dec is not None   and  (blk.statements[-1],False) in self.dec.codegen.ailexpr2cnode  :
                tmp_bb=self.dec.codegen.ailexpr2cnode[(blk.statements[-1],False)].c_repr().split(',')#[1][2:-1]
                print(tmp_bb)
                if function.name in ["sprintf","sscanf"]:
                    tmp_bb=tmp_bb[1][2:-1]
                else:
                    tmp_bb=tmp_bb[2][2:-1]
                print(tmp_bb)
                if bb!=tmp_bb:
                    bb=tmp_bb
                    if '%' in bb :
                        patttern=bb.split('%')
                    else:
                        patttern=[]
                    
        except Exception as e:
            print(e)
        
            
        if len(bb)==0:
            try:
                if function.name in ["sprintf","sscanf"]:
                    bb=self.get_stringby_use_def(d1,state)
                else:
                    bb=self.get_stringby_use_def(d2,state)
                patttern=bb.split('%')
            except Exception as e:
                bb=""
                patttern=[]
        
        print("for debug")
        
        print(" final bb= ",bb)
        print(blk.statements[-1])
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        extra_definations=[]
        arg_number = len(patttern)-1
        
        
        for stmt in blk.statements:
            #print(stmt)
            if type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and   type(stmt.src) == ailment.expression.StackBaseOffset and stmt.src not in blk.statements[-1].args :
                blk.statements[-1].args.append(stmt.src)
                
            elif type(stmt) == ailment.statement.Store :
                blk.statements[-1].args.append(stmt.addr)
        
        
        
        
        
        atom= d0.atom
        ## atom will be modified if some conditions are stisified
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            
            check_flag=False  # to check if we have catched expected conditions or not
            
            #Call (target: Load(addr=(0x5071e0<32> - 0x71b8<32>), size=4, endness=Iend_LE), prototype: None, args: None)
            # call_statement.target.addr is Sub(0x5071e0<32>, 0x71b8<32>)
            if type(blk.statements[-1]) == ailment.statement.Call and blk.statements[-1].args is None :
                    atom=d0.atom
                    #it need furthor investigation
                    check_flag=True
            
    
            elif type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >0 :
                arg0=call_statement.args[0] 
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    check_flag=True
                # arg0=s0
                elif hasattr(arg0,'reg_offset') :
                    reg=state.arch.registers[arg0.tags['reg_name']]
                    temp_def=next(iter(state.get_definitions(Register(reg[0],reg[1]))))
                    atom=temp_def.atom
                    check_flag=True
                # Call (target: 0x600354<32>, prototype: (char*, unsigned long (32 bits), char*, ...) -> int│ipdb>(32 bits), args: [Load(addr=stack_base-108, size=4, endness=Iend_LE), 0x8<32>, 0x4a48bc<3│ipdb>2>, s5<4>]) 
                #'''
                elif type(call_statement.args[0]) == ailment.expression.Load and  hasattr(call_statement.args[0],'addr') and type(call_statement.args[0].addr) == ailment.expression.StackBaseOffset :
                    atom=d0.atom
                    #it need furthor investigation
                    atom=MemoryLocation(SpOffset(state.arch.bits,call_statement.args[0].addr.offset),arg0.size)
                    check_flag=True
                    
                elif type(call_statement.args[0]) == ailment.expression.Load and  hasattr(call_statement.args[0],'addr') and type(call_statement.args[0].addr) == ailment.expression.BinaryOp and type(call_statement.args[0].addr.operands[1])==ailment.expression.Const:
                    atom=d0.atom
                    #it need furthor investigation
                    atom=MemoryLocation(SpOffset(state.arch.bits,call_statement.args[0].addr.operands[1].value),call_statement.args[0].addr.operands[1].size)
                    check_flag=True
                    
                #'''
                
                
                if arg_number==0 :
                    arg_number =len(blk.statements[-1].args)-extrs_defination_location 
                
                #'''
                if arg_number > 1 :
                    for i in range(0,arg_number) :
                        try:
                            #arg_number-=1   #make sure extra definations will not be collected again latter
                            if extrs_defination_location+i >= len(call_statement.args):
                                continue
                            arg=call_statement.args[extrs_defination_location+i]
                            if hasattr(arg,'reg_offset') :
                                #arg.tags['reg_name']
                                reg=state.arch.registers[arg.tags['reg_name']]
                                #temp_def=next(iter(state.get_definitions(Register(reg[0],reg[1]))))
                                temp_def=[d for d in state.get_definitions(Register(reg[0],reg[1])) ]
                                if len(temp_def)>0 :
                                    extra_definations.append(temp_def[0])

                            elif hasattr(arg,'base') :
                                mem_atom=MemoryLocation(SpOffset(state.arch.bits,arg.offset),arg.size)
                                temp_def=[d for d in state.get_definitions(mem_atom)]
                                if len(temp_def)>0 :
                                    extra_definations.append(temp_def[0])
                                else:
                                    parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[extrs_defination_location+i], state.arch.bytes),  self._analysis.project.arch.registers )
                                    def0 = state.get_definitions(parameter_atom)
                                    temp_def = [d for d in def0]
                                    extra_definations.append(temp_def[0])
                            elif type(arg) == ailment.expression.Load and hasattr(arg,'addr') and type(arg.addr) == ailment.expression.StackBaseOffset:
                                mem_atom=MemoryLocation(SpOffset(state.arch.bits,arg.addr.offset),arg.size)
                                temp_def=[d for d in state.get_definitions(mem_atom)]
                                if len(temp_def)>0 :
                                    extra_definations.append(temp_def[0])
                                else:
                                    if extrs_defination_location+i >= len(cc.ARG_REGS):
                                        continue
                                    parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[extrs_defination_location+i], state.arch.bytes),  self._analysis.project.arch.registers )
                                    def0 = state.get_definitions(parameter_atom)
                                    temp_def = [d for d in def0]
                                    extra_definations.append(temp_def[0])
                        except Exception as e:
                            print(' error at 916  ', e)
                            continue
                          
                #'''


                 
            else:
                for smt in blk.statements :
                    if type(smt) == ailment.statement.Assignment and type(smt.src) == ailment.expression.StackBaseOffset and  smt.dst.tags['reg_name']== state.arch.register_names[d0.atom.reg_offset]:#  'a0':
                        atom=MemoryLocation(SpOffset(state.arch.bits,smt.src.offset),d0.size)
                        check_flag=True
                        break
                
            
            
            
        
            
            
        
        
       
              
        
        
        if arg_number > 1 :# and len(extra_definations)==0 :#  and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) ==0:
            for i in range(1,arg_number) :
                try:
                    parameter_position = extrs_defination_location+i#i
                    if parameter_position >= len(cc.ARG_REGS) :
                        continue

                    parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),  self._analysis.project.arch.registers )

                    def0 = state.get_definitions(parameter_atom)
                    temp_def = [d for d in def0][0]

                    #d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=i)
                    extra_definations.append(temp_def)
                except Exception as e:
                    print(' error at 956  ', e)
                    continue
                          
        
        
        
        
        length=-1
        if function.name in  ["snprintf","vsnprintf"]:# == "snprintf":
            if type(blk.statements[-1].args[1]) ==ailment.expression.Const :
                length=blk.statements[-1].args[1].value
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
        
        
        # add the effect of sprintf
        # '''
        # caller_function = self._analysis.project.kb.functions.floor_func(src_ins_addr)
        # ReturnValueTag   SideEffectTag   LocalVariableTag
        print("token= ", bb)
        
        
        
        tags = {LocalVariableTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':bb,'length':length})}
        
        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)

        # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

        tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
        # state.add_use(atom, tmp_codeloc)
        mv = state.kill_and_add_definition(atom, tmp_codeloc, data, tags=tags)
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        #ff = [d for d in ff_defs][0]
        ff=next( iter(ff_defs) )

        # to overwrite mov eax,o, which effect the defination of rax
        if ff not in state.dep_graph.graph.nodes():
            state.dep_graph.add_node(ff)
        # state.dep_graph.add_edge(d0, ff)
        state.dep_graph.add_edge(d1, ff)
        state.dep_graph.add_edge(d2, ff)
        # state.add_use(ff, tmp_codeloc)
        
        for i in range(len(extra_definations) ):
            state.dep_graph.add_edge(extra_definations[i], ff)
            
            

        if function.name in ["snprintf","vsnprintf"]:# == "snprintf":
            state.dep_graph.add_edge(d3, ff)
            
            
        ff_list=[ff]    
            
        another_ff=self.get_memoryDef_by_use_def(d0,state)
        if another_ff is not None and another_ff.atom != atom :
            mv = state.kill_and_add_definition(another_ff.atom, tmp_codeloc, data, tags=tags)
            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
            #ff = [d for d in ff_defs][0]
            ff=next( iter(ff_defs) )
            ff_list.append(ff)

            # to overwrite mov eax,o, which effect the defination of rax
            if ff not in state.dep_graph.graph.nodes():
                state.dep_graph.add_node(ff)
            # state.dep_graph.add_edge(d0, ff)
            state.dep_graph.add_edge(d1, ff)
            state.dep_graph.add_edge(d2, ff)
            # state.add_use(ff, tmp_codeloc)

            for i in range(len(extra_definations) ):
                state.dep_graph.add_edge(extra_definations[i], ff)



            if function.name in ["snprintf","vsnprintf"]:# == "snprintf":
                state.dep_graph.add_edge(d3, ff)
            
            
        ''' I removed it recently
        elif function.name == "sprintf":
           
            tags_2 = {ReturnValueTag(
                function=function.addr,
                metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
            #atom = Register(state.arch.ret_offset, state.arch.bytes)#(16, 4)
            ret_register_name=state.arch.register_names[state.arch.ret_offset]
            ret_register_name_size=state.arch.registers[ret_register_name]
            atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
            
            # data: MultiValues = state.register_definitions.load( rdi_pred.atom.reg_offset, size=rdi_pred.atom.size)
            data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
            # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
            mv = state.kill_and_add_definition(atom, tmp_codeloc, data, tags=tags_2)  # rdi_pred.codeloc
            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
            new_rax = [d for d in ff_defs][0]
            state.dep_graph.add_edge(ff, new_rax)
        '''
        
        
        '''  this is a ascond part of a treatement I add it first at handle_NK, when a function forget to referece a stack variable
        if function.name in ["sprintf", "sscanf"]:
            snd_blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr,False)
            if arg_number > 1 :# and len(extra_definations)==0 :#  and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) ==0:
                for i in range(2,arg_number+1) :
                    if call_statement.args[i].value==0:
                        parameter_position = i#i
                        if parameter_position >= len(cc.ARG_REGS) :
                            continue
                        parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),  self._analysis.project.arch.registers )
                        for smt in snd_blk.statements:
                            if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name']==state.arch.register_names[parameter_atom.reg_offset] :
                                #print(smt)
                                if type(smt.src)==ailment.expression.Register and smt.src.reg_offset in defination_dictionary:
                                    defs=defination_dictionary[smt.src.reg_offset]
                                    state.dep_graph.add_edge(defs, ff)
                                break
                            
          '''              
                    

           
        #'''
        if function.name in ["sprintf", "sscanf"]:
            print("--------------------Start sprintf-----------")
            def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
            def_explorer.set_current_state(state)
            def_explorer.set_current_codeloc(codeloc)
            def_explorer.set_RDA_handler(self)
            def_explorer.set_current_fucntion(self.cur_fun)
            backtrack_definations(def_explorer, reg_defs=ff_list, result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
            print("----------------------End sprintf----------------")
            
        
        
        return True, state

    def handle_sprintf(self, state, codeloc):
        # print('I am inside sprintf handleer')
        function = self._analysis.project.kb.functions.function(name="sprintf")
        return self.handle_sprintf_xx(function, state, codeloc)
    
    def handle_vsnprintf(self, state, codeloc):
        # print('I am inside sprintf handleer')
        function = self._analysis.project.kb.functions.function(name="vsnprintf")
        return self.handle_sprintf_xx(function, state, codeloc)

    
    def handle_sscanf(self, state, codeloc):
        print('I am inside sscanf handleer')
        function = self._analysis.project.kb.functions.function(name="sscanf")
        flag,state=self.handle_system_xx(function, state, codeloc)
        print("\n now lets connect the rest")
        #return self.handle_sprintf_xx(function, state, codeloc)
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state) 
        if 1==1:
            extrs_defination_location=2
            try:
                bb=""
                if d1.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                    bb1=self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr]
                    i=0
                    while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                        i+=1
                    bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                
                  
        
                patttern=bb.split('%')
                
            except Exception as e:
                print(e)
                bb=""
                patttern=[]
                dst_def = d1
                d2=d1
                '''
                print(e)
                import ipdb;
                ipdb.set_trace()
                pass
                '''
                
        
        
        
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        #
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr) 
        ff=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0,blk=blk)
        #ff=self.get_memory_defination(d0,function,state,codeloc)
        if (len(patttern)-1==0 or len(patttern)==0) and type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >1 :
            try:
                i=0
                while str(self.cfg.project.loader.memory.load(blk.statements[-1].args[1].value, i))[i+1] != '\\':
                    i+=1
                bb=str(self.cfg.project.loader.memory.load(blk.statements[-1].args[1].value, i-1))[2:-1]
                patttern=bb.split('%')
            except Exception as e:
                print(e ,"error at 1347")
                '''
                print(e)
                import ipdb;
                ipdb.set_trace()
                pass
                '''
        
        if len(patttern)-1==0 or len(patttern)==0:
            bb=self.get_stringby_use_def(d1,state)
            patttern=bb.split('%')
            #return True ,state
                
        
        
        
        
       
        
        print("for debug")
        print(" final bb= ",bb)
        print(blk.statements[-1])
       
        
        
        extra_definations=[]
        arg_number = len(patttern)-1
        extrs_defination_location=2
        
        if arg_number==0 :
            arg_number =len(blk.statements[-1].args)-2
        
        for stmt in blk.statements:
            #print(stmt)
            if type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and   type(stmt.src) == ailment.expression.StackBaseOffset and stmt.src not in blk.statements[-1].args :
                blk.statements[-1].args.append(stmt.src)
            elif type(stmt) == ailment.statement.Store :
                blk.statements[-1].args.append(stmt.addr)
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''  
        
        
        if arg_number > 1 :# and len(extra_definations)==0 :#  and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) ==0:
            for i in range(0,arg_number) :
                try:
                    parameter_position = extrs_defination_location+i#i
                    if parameter_position >=  len(blk.statements[-1].args  ) :
                         continue
                    temp_d0 = self.get_def_from_parameter(function, parameter_position=parameter_position, state=state)
                    temp_def=self.get_memory_defination(temp_d0,function,state,codeloc,defination_only=False,defination_location=parameter_position,blk=blk)
                    if temp_def not in state.dep_graph.graph.nodes():
                        state.dep_graph.add_node(temp_def)
                        
                    extra_definations.append(temp_def)
                except Exception as e:
                    print(e)
                    print("error is here  inside sscanf")
        
        
        
        
        
        for i in range(len(extra_definations) ):
            state.dep_graph.add_edge(ff,extra_definations[i])
        
        return True,state
        
        
        
        
        
        
    
    def handle_snprintf(self, state, codeloc):
        print("inside snprintf")
        function = self._analysis.project.kb.functions.function(name="snprintf")
        return self.handle_sprintf_xx(function, state, codeloc)

    def handle_system_xx(self, function, state, codeloc, position=0,blk=None):  # state, codeloc, function):
        print(" inside ->", function.name)

        '''
        cc = function.calling_convention

        parameter_position = position# 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]
        
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        
        if d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
            return True, state
            
        
        '''
        
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        
        #blk=self.get_clinic_block(self.clinic,d0.codeloc.block_addr)
        if blk is None:
            blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        print("for debug")
        print(blk.statements[-1])
        #write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
        #os.system("dot -Tsvg -o ss.svg zz.dot")
        
        '''
        if function.name=="sscanf":#"system" and self.cur_fun.name=="sub_3a170": #"system":
            write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
            os.system("dot -Tsvg -o ss_system.svg zz.dot")

            import ipdb;
            ipdb.set_trace()
            pass
        '''
        
        '''
        global_counter[0]+=1
        if global_counter[0]==2:
            import ipdb;
            ipdb.set_trace()
            pass
        
        '''
        
       
        '''
        write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
        os.system("dot -Tsvg -o ss.svg zz.dot")
        import ipdb;
        ipdb.set_trace()
        pass
        
        '''
        ff_list=[d0]
        ff=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0,blk=blk)
        ff_list=[d0,ff]
        tmp_ff=self.get_memoryDef_by_use_def(d0,state)
        if tmp_ff is not None :
            ff=[d for d in state.get_definitions(tmp_ff.atom)]
            if len(ff)!=0:
                ff_list.append(ff[0])
        
        # rd_ddg_graph = rd.dep_graph
        # Instantiate the object that will walk back the dep_graph.
        def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
        def_explorer.set_current_state(state)
        def_explorer.set_current_codeloc(codeloc)
        def_explorer.set_RDA_handler(self)
        def_explorer.set_current_fucntion(self.cur_fun)
        for item in ff_list:
            backtrack_definations(def_explorer, reg_defs=[item], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
        
        
        if 1==1 and abs( state.current_codeloc.ins_addr - int(0x3d9c4) ) <=8 and  function.name in  ["system"]:
            write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
            os.system("dot -Tsvg -o ss.svg zz.dot")
            import ipdb;
            ipdb.set_trace()
            pass
        
        

        #'''
        #magic_graph_print(state.dep_graph.transitive_closure(d0))
        

        return True, state

    # SINKS =['system', '___system', 'bstar_system', 'popen', 'doSystemCmd', 'doShell', 'twsystem', 'CsteSystem', 'cgi_deal_popen', 'ExecShell', 'exec_shell_popen', 'exec_shell_popen_str','wl_exec_cmd','execve']   execve , execl, eval, eval, sh, send, execlp
    
    def handle_wl_exec_cmd(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="wl_exec_cmd")
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        return self.handle_system_xx(function, state, codeloc)
    
    def xx_handle__eval(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="_eval")
        return self.handle_system_xx(function, state, codeloc)
    
    def xx_handle_eval(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="eval")
        return self.handle_system_xx(function, state, codeloc)
    
        function = self._analysis.project.kb.functions.function(name="sh")
        return self.handle_system_xx(function, state, codeloc)
    
    
    def handle_exec_shell_popen_str(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="exec_shell_popen_str")
        return self.handle_system_xx(function, state, codeloc)
    
   
    
    def handle_exec_shell_popen(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="exec_shell_popen")
        return self.handle_system_xx(function, state, codeloc)
    
    def handle_ExecShell(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="ExecShell")
        return self.handle_system_xx(function, state, codeloc)
    
    def handle_cgi_deal_popen(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="cgi_deal_popen")
        return self.handle_system_xx(function, state, codeloc)
    
    def handle_CsteSystem(self,state,codeloc):
        function = self._analysis.project.kb.functions.function(name="CsteSystem")
        return self.handle_system_xx(function, state, codeloc)
        
    def handle_system(self, state, codeloc):
        print("inside system")
        function = self._analysis.project.kb.functions.function(name="system")
        return self.handle_system_xx(function, state, codeloc)

    def handle_twsystem(self, state, codeloc,blk=None):
        function = self._analysis.project.kb.functions.function(name="twsystem")
        return self.handle_system_xx(function, state, codeloc, position=0,blk=blk)

    def handle_bstar_system(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="bstar_system")
        return self.handle_system_xx(function, state, codeloc)

    def handle_popen(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="popen")
        return self.handle_system_xx(function, state, codeloc)

    def handle____system(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="___system")
        return self.handle_system_xx(function, state, codeloc)

    def handle_doSystemCmd(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="doSystemCmd")
        patttern=[]
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        print("inside handle local")
        print(blk)
        xx=[]
        
        '''
        if d0.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
            bb1=self.cfg.insn_addr_to_memory_data[d0.codeloc.ins_addr]
            i=0
            while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                   i+=1
            bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
        else:
            bb=get_strings(d0,self.cfg,state.dep_graph)
        '''
            
        d1 = self.get_def_from_parameter(function, parameter_position=0, state=state)  # the position is 0, I used d1 just because I copied the code from some other places
        
        
        
        '''
        if abs(state.current_codeloc.ins_addr - int(0x44ddf4) ) <=8:
            import ipdb;
            ipdb.set_trace()
            pass
        '''  
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        if  d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:                        
                        pred=[d for d in state.dep_graph.predecessors(d1)]
                        '''
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        bb=""
                        if len(pred)==1 and type(pred[0].atom)!=MemoryLocation: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                            pred=[d for d in state.dep_graph.predecessors(pred[0])]
                        for defination in pred :
                                if type(defination.atom)==MemoryLocation  and 'readonly' in  f'{defination}' :
                                    i=0
                                    while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                          i+=1
                                    bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]                                    
                                    break
                        if len(bb)==0 and d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:
                            #bb1=self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr]
                            i=0
                            while str(self.cfg.project.loader.memory.load(d1.atom.addr, i+1))[i+1] != '\\':
                                  i+=1
                            bb=str(self.cfg.project.loader.memory.load(d1.atom.addr, i-1))[2:-1] 
                            #bb=str(self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr].content)[2:-1]                               
                        
                        if len(bb)>2:
                            #bb=str(bb)[2:-1]
                            patttern=xx=bb.split("%")
                        print(xx)
        
        
        
        
        
        
        if 1==0 and (blk.statements[-1],False) in self.dec.codegen.ailexpr2cnode :
            xx=self.dec.codegen.ailexpr2cnode[(blk.statements[-1],False)].c_repr().split('%')
            #tp_xx=xx
            print(xx)
            patttern=xx
            #xx=xx.split('"')
        print("----------")
        
        '''
        if function_name=="sub_430380":#"sub_40e898":
            import ipdb;
            ipdb.set_trace()
            pass
        ''' 
          
        
        # to address similar incidence sub_184d4(v5, "iserver_passcode", &v2);
        try:
            if  blk is not None and hasattr(blk,"statements") and len(blk.statements) >0 and type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >1  :
                
                d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
                
                if len(xx)> 1 : 
                    bb=xx[0]#[1]
                elif d0.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                    bb1=self.cfg.insn_addr_to_memory_data[d0.codeloc.ins_addr]
                    i=0
                    while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                        i+=1
                    bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                else:
                    bb=get_strings(d0,self.cfg,state.dep_graph)



                if  "%" in bb:
                    patttern=bb.split('%')
                print("bb=",bb,patttern)
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                '''    



                extrs_defination_location=1
                extra_definations=[]
                arg_number = len(patttern)-1
                print("arg_number -> ", arg_number)

                if arg_number > 0 :
                    for i in range(0,arg_number) :
                        #arg_number-=1   #make sure extra definations will not be collected again latter
                        if not hasattr(blk.statements[-1],'args'):
                            continue
                        arg=blk.statements[-1].args[extrs_defination_location+i]
                        print(arg)
                        if hasattr(arg,'reg_offset') :
                            #arg.tags['reg_name']
                            reg=state.arch.registers[arg.tags['reg_name']]
                            #temp_def=next(iter(state.get_definitions(Register(reg[0],reg[1]))))
                            temp_def=[d for d in state.get_definitions(Register(reg[0],reg[1])) ]
                            if len(temp_def)>0 :
                                extra_definations.append(temp_def[0])
                            
                        elif hasattr(arg,'base') :
                            mem_atom=MemoryLocation(SpOffset(state.arch.bits,arg.offset),arg.size)
                            temp_def=[d for d in state.get_definitions(mem_atom)]
                            if len(temp_def)>0 :
                                extra_definations.append(temp_def[0])
                            else:
                                temp_def = self.get_def_from_parameter(function, parameter_position=extrs_defination_location+i, state=state)
                                if not None :
                                    extra_definations.append(temp_def)
                                    
                                '''
                                parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[extrs_defination_location+i], state.arch.bytes),  self._analysis.project.arch.registers )
                                def0 = state.get_definitions(parameter_atom)
                                temp_def = [d for d in def0]
                                if len(temp_def)>0 :
                                    extra_definations.append(temp_def[0])
                                '''
                        elif type(arg) == ailment.expression.Load and hasattr(arg,'addr') and type(arg.addr) == ailment.expression.StackBaseOffset:
                            mem_atom=MemoryLocation(SpOffset(state.arch.bits,arg.addr.offset),arg.size)
                            temp_def=[d for d in state.get_definitions(mem_atom)]
                            if len(temp_def)>0 :
                                extra_definations.append(temp_def[0])
                            else:
                                parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[extrs_defination_location+i], state.arch.bytes),  self._analysis.project.arch.registers )
                                def0 = state.get_definitions(parameter_atom)
                                temp_def = [d for d in def0]
                                if len(temp_def)>0 :
                                    extra_definations.append(temp_def[0])
                    print("extra_definations -> ",extra_definations)
                    '''
                    if bb==" td_acs_dbg -i %s  auto_bandwidth_measure 5" :
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    '''
                        
                    for d0 in extra_definations:
                        def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
                        
                        def_explorer.set_current_state(state)
                        def_explorer.set_current_codeloc(codeloc)
                        #def_explorer.set_RDA_handler(self)
                        #def_explorer.set_current_fucntion(self.cur_fun)
                        
                        def_explorer.set_RDA_handler(self)
                        def_explorer.set_current_fucntion(self.cur_fun)
                        backtrack_definations(def_explorer, reg_defs=[d0], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
                        #backtrack_definations(def_explorer, reg_defs=[d0], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
        

                    return True, state
                    import ipdb;
                    ipdb.set_trace()
                    pass
            
            
            
            
            elif  len(patttern) >0   :  # when blk does not cover all the parameters
                extrs_defination_location=1
                extra_definations=[]
                arg_number = len(patttern)-1
                print("arg_number -> ", arg_number)

                if arg_number > 0 :
                    for i in range(0,arg_number) :
                        d1 = self.get_def_from_parameter(function, parameter_position=extrs_defination_location+i, state=state)
                        extra_definations.append(d1)
                    
                    for d0 in extra_definations:
                        def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
                        def_explorer.set_current_state(state)
                        def_explorer.set_current_codeloc(codeloc)
                        #def_explorer.set_RDA_handler(self)
                        #def_explorer.set_current_fucntion(self.cur_fun)
                        def_explorer.set_RDA_handler(self)
                        def_explorer.set_current_fucntion(self.cur_fun)
                        backtrack_definations(def_explorer, reg_defs=[d0], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
                return True, state
                
            
            
            else:
                #d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
                #if self.dec.codegen.ailexpr2cnode[(blk.statements[-1],False)].c_repr()
                return self.handle_system_xx(function, state, codeloc)
                 
                
        except Exception as e:
            print(e)
            return True, state
            import ipdb;
            ipdb.set_trace()
            pass
        
        
        

    def handle_doShell(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="doShell")
        return self.handle_system_xx(function, state, codeloc)
    def handle_doSystem(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="doSystem")
        
        cc = function.calling_convention

        parameter_position = 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        
        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]
        
        
        if d0.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
            bb1=self.cfg.insn_addr_to_memory_data[d0.codeloc.ins_addr]
            i=0
            while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                i+=1
            bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
        else:
            bb=get_strings(d0,self.cfg,state.dep_graph)
        
        
        
        patttern=bb.split('%')
        '''
        if bb=="iwpriv %s set DefaultKeyID=%s" :
            import ipdb;
            ipdb.set_trace()
            pass
        '''    
        
          
        
        extrs_defination_location=1
        extra_definations=[]
        arg_number = len(patttern)#-1
        
        if arg_number > 1 :
            for i in range(1,arg_number) :
                if i >=len(cc.ARG_REGS[parameter_position]):
                    break
                parameter_position = i
                parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),  self._analysis.project.arch.registers )
        
                def0 = state.get_definitions(parameter_atom)
                d0 = [d for d in def0][0]
                
                #d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=i)
                extra_definations.append(d0)
        
            
            '''
            if bb=="iwpriv %s set DefaultKeyID=%s" :
                import ipdb;
                ipdb.set_trace()
                pass
            #'''  
            for d0 in extra_definations:
                def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
                def_explorer.set_RDA_handler(self)
                def_explorer.set_current_fucntion(self.cur_fun)
                backtrack_definations(def_explorer, reg_defs=[d0], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
        

        return True, state
    
    
    
    def handle__system(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="_system")
        
        cc = function.calling_convention

        parameter_position = 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        
        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]
        
        
        if d0.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
            bb1=self.cfg.insn_addr_to_memory_data[d0.codeloc.ins_addr]
            i=0
            while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                i+=1
            bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
        else:
            bb=get_strings(d0,self.cfg,state.dep_graph)
        
        
        
        patttern=bb.split('%')
        '''
        if bb=="iwpriv %s set DefaultKeyID=%s" :
            import ipdb;
            ipdb.set_trace()
            pass
        '''    
        
          
        
        extrs_defination_location=1
        extra_definations=[]
        arg_number = len(patttern)#-1
        
        if arg_number > 1 :
            for i in range(1,arg_number) :
                if i >=len(cc.ARG_REGS[parameter_position]):
                    break
                parameter_position = i
                parameter_atom = Atom.from_argument( SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),  self._analysis.project.arch.registers )
        
                def0 = state.get_definitions(parameter_atom)
                d0 = [d for d in def0][0]
                
                #d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=i)
                extra_definations.append(d0)
        
            
            '''
            if bb=="iwpriv %s set DefaultKeyID=%s" :
                import ipdb;
                ipdb.set_trace()
                pass
            #'''  
            for d0 in extra_definations:
                def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
                def_explorer.set_RDA_handler(self)
                def_explorer.set_current_fucntion(self.cur_fun)
                backtrack_definations(def_explorer, reg_defs=[d0], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
        

        return True, state
        
        
    
    def handle_execve(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="execve")
        return self.handle_system_xx(function, state, codeloc, 1)
    
    def handle_execl(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="execl")
        return self.handle_system_xx(function, state, codeloc, 1)
    
    def handle_ExeCmd(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="ExeCmd")
        return self.handle_system_xx(function, state, codeloc)
    
    
    def XX_handle_kd_doCommand(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="kd_doCommand")
        return self.handle_system_xx(function, state, codeloc)
    
    
    
    
    def handle_strchr_xx(self, function, state, codeloc):  # state, codeloc, function):
        print(" inside ->", function.name)
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        dd0=d0
        #print("d0 is ", d0)
        #d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0)
        #print("ff is",d0)
        data: MultiValues = state.register_definitions.load(dd0.atom.reg_offset, size=d0.atom.size)
        #d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0)
        
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        
        tags_2 = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        
        if d0.atom == atom:  #For ARM architecture
            d0.tags.clear()
            d0.tags.update(tags_2)
            new_rax=d0
        
        
        try:
            new_rax=d0
            mv = state.kill_and_add_definition(atom, state.current_codeloc, data, tags=tags_2)
            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
            new_rax = [d for d in ff_defs][0]
            #ff_defs = state.get_definitions(atom)
            #new_rax = [d for d in ff_defs][0]
        except Exception as e:
            print(e)
        #'''
        state.dep_graph.add_edge(d0,new_rax)
        if 1==0:# function.name=='strchr':
            strchr_counter[0]+=1
            write_dot(state.dep_graph.transitive_closure(new_rax), "zz.dot")
            os.system(f'dot -Tsvg -o {str(strchr_counter[0])}_{function.name}.svg zz.dot')
            
            write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
            os.system(f'dot -Tsvg -o d0-{str(strchr_counter[0])}_{function.name}.svg zz.dot')
            #import ipdb;
            #ipdb.set_trace()
            #pass
         #'''
            
       
        
        #write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
        #os.system(f'dot -Tsvg -o {str(hex(codeloc.ins_addr))}_{function.name}.svg zz.dot')
        return True, state
    
    # it is duplicate the string
    def handle_strdup(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strdup")
        return self.handle_strchr_xx(function, state, codeloc)
    def handle_strndup(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strndup")
        return self.handle_strchr_xx(function, state, codeloc)
    
    def handle_strrchr(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strrchr")
        return self.handle_strchr_xx(function, state, codeloc)
    
    def handle_strstr(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strstr")
        return self.handle_strchr_xx(function, state, codeloc)
    
    
    def handle_stristr(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="stristr")
        return self.handle_strchr_xx(function, state, codeloc)
    
    
    def handle_strpbrk(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strpbrk")
        return self.handle_strchr_xx(function, state, codeloc)
    
    def handle_atoi(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="atoi")
        return self.handle_strchr_xx(function, state, codeloc)
    
    
    def handle_strspn(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strspn")
        return self.handle_strchr_xx(function, state, codeloc)
    
    
    
    
    def handle_strchr(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="strchr")
        return self.handle_strchr_xx(function, state, codeloc)
        
        
        print("inside strchr")
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0)
        
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        
        tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        
        if d0.atom == atom:  #For ARM architecture
            d0.tags.clear()
            d0.tags.update(tags_2)
            new_rax=d0
        
        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        try:
            mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
        except Exception as e:
            print(e)
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
            
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(d0,new_rax)
        
        return True, state
        
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        
        
                    

                    
    def handle_getTokens(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="getTokens")   
        
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        d2 = self.get_def_from_parameter(function, parameter_position=2, state=state)
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr) 
        d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0)
        ff=self.get_memory_defination(d2,function,state,codeloc)
         
        tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        ff.tags.update(tags)
        
        
        state.dep_graph.add_node(ff)
        
        state.dep_graph.add_edge(d0, ff)
        
        return True, state
        
        
        
        
        
        

    def handle_strcpy_xx(self, function, state, codeloc):  # , function):
        """
        Handles the simulation of string manipulation functions such as `strcpy`, `strcat`, `strncpy`, etc., 
        within a binary analysis context. This function is part of a taint analysis framework and is responsible 
        for tracking memory definitions, taint propagation, and dependency graph updates for string-related 
        operations.
        Args:
            function (Function): The function object representing the string manipulation function being analyzed.
            state (State): The current program state, including memory, registers, and dependency graph.
            codeloc (CodeLocation): The code location where the string manipulation function is invoked.
        Returns:
            tuple: A tuple containing:
                - bool: Always `True`, indicating successful handling.
                - State: The updated program state after processing the string manipulation function.
        Key Operations:
            - Extracts and processes function parameters to identify memory definitions.
            - Handles taint propagation for memory locations affected by the string manipulation function.
            - Updates the dependency graph with new nodes and edges based on the function's effects.
            - Tags memory definitions with metadata for further analysis.
            - Performs backtracking of definitions if the function is identified as a taint sink (e.g., `strcpy`, `strcat`).
        Notes:
            - The function supports additional string manipulation functions like `strncpy`, `strlcpy`, `strncat`, 
                `memcpy`, and `memmove`.
            - Handles exceptions gracefully to ensure robustness during analysis.
            - Includes optional debugging hooks for inspecting the dependency graph and program state.
        Raises:
            Exception: If an error occurs during backtracking or dependency graph updates.
        Example Usage:
            This function is typically invoked as part of a larger binary analysis framework to simulate 
            the effects of string manipulation functions and track taint propagation.
        """

        # print('I am inside strcpy handleer heheh')
        # sink_name = 'strcpy'
        # function = project.kb.functions.function(name="strcpy")
        # function = self._analysis.project.kb.functions.function(codeloc.block_addr)
        print(" inside ",function.demangled_name)
        print(function.name)
        

        '''
        cc = function.calling_convention

        parameter_position = 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        parameter_position_1 = 1
        parameter_atom_1 = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position_1], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        # in the future  we need to check if there is a third parameter or not
        parameter_position_2 = 2
        parameter_atom_2 = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position_2], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]
        '''
        
        
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
        dd1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
        bb="" #0
        
        try:
            if d1.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data : #参数寄存器的赋值位置
                bb1=self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr]
                bb=str(bb1.content)[2:-1]
                i=0
                while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                    i+=1
                    bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
            else:
                bb=get_strings(d2,self.cfg,state.dep_graph)
        
                
        except Exception as e:
            bb=""
               
        print("state.current_",state.current_codeloc)    

        print("d0",d0)
        print("d1",d1)
        #print("d2",d2)
        print("bb",bb)

        
        # if 1==0 and  function.name=="strcpy":# and abs( state.current_codeloc.ins_addr- int(0x823f8) )<=8:#strcpy_counter[0]==2:          0x82494
        #     rrrrr=0
            
        #     write_dot(state.dep_graph.transitive_closure(d1), "zz.dot")
        #     os.system(f'dot -Tsvg -o {strcpy_counter[0]}_strcpy.svg zz.dot')
        #     #'''
        #     import ipdb;
        #     ipdb.set_trace()
        #     pass
        #     #'''
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr) 
        d1=self.get_memory_defination(d1,function,state,codeloc,defination_only=True,defination_location=1)
        ff=self.get_memory_defination(d0,function,state,codeloc,defination_only=False, defination_location=0,blk=blk)
        
        strcpy_counter[0]+=1
        #print("state.current_",state.current_codeloc)
        # if 1==0 and  abs( state.current_codeloc.ins_addr- int(0x6e338) )<=8:#strcpy_counter[0]==2:          0x82494
        #     rrrrr=0
            
        #     write_dot(state.dep_graph.transitive_closure(d1), "zz.dot")
        #     os.system(f'dot -Tsvg -o {strcpy_counter[0]}_strcpy.svg zz.dot')
        #     #'''
        #     import ipdb;
        #     ipdb.set_trace()
        #     pass
            #'''
        
        #strncat(local_158,__src,0x100);
        length=-1
        is_tainted_falg=False
        try:
            if function.name in ["strncpy","strlcpy","strncat","strncpy","memcpy","memmove"]:
                if type(blk.statements[-1].args[2]) ==ailment.expression.Const :
                    length=blk.statements[-1].args[2].value     
                    tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'length':length})}
                    ff.tags.update(tags)
                    # save 
                    # with open(f"{self.cur_func.name}.json","a+") as f:
                    #     json.dump(
                    #         {
                    #             'function':function.name,
                    #             'block_addr':state.current_codeloc.block_addr,
                    #             'blk_statements_args':blk.statements[-1].args[2],
                    #             'd3_length':length
                    #         }
                        # )
                else:
                    d2 = self.get_def_from_parameter(function, parameter_position=2, state=state)
                    d2=self.get_memory_defination(d2,function,state,codeloc,defination_only=True,defination_location=2)
                    is_tainted_falg= self.is_defination_tainted(d2,function,state)
                    # with open(f"{self.cur_func.name}.json","a+") as f:
                    #     json.dump(
                    #         {
                    #            "d2":d2,
                    #            "is_tainted_falg":is_tainted_falg,
                    #             "cur_function":self.cur_fun.name,
                    #         },f
                    #     )

                        
        except Exception as e:
            print("error 1570", e)
            tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'length':length})}
            ff.tags.update(tags)
        
        
        #def1 = state.get_definitions(parameter_atom_1)
        #d1 = [d for d in def1][0]
        
        
        
        if len(bb)> 5  and type(ff.atom)==MemoryLocation:
            #print("ff", ff.atom)
            #print(ff)
            tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'length':length})}
            ff.tags.update(tags)
                
                
        
        '''
        write_dot(state.dep_graph.transitive_closure(d1), "zz.dot")
        os.system("dot -Tsvg -o ss.svg zz.dot")
        import ipdb;
        ipdb.set_trace()
        pass
        '''

        state.dep_graph.add_node(ff)
        if "cat" in function.demangled_name:
            state.dep_graph.add_edge(d0, ff)
        state.dep_graph.add_edge(d1, ff)
        #
        #d1=self.get_memory_defination(d1,function,state,codeloc,defination_only=True,defination_location=1)
        # when this instruction return a wron defination, so we have a back up link from vex other otham depending only on clinic, which sometimes fail
        if dd1.atom != d1.atom :
            state.dep_graph.add_edge(dd1, ff)

        state.add_memory_use_by_defs([ff], state.current_codeloc)
        state.add_use_by_def(ff, state.current_codeloc, None)
        # state.add_use(ff, tmp_codeloc)
        '''
        if self.cur_fun.name=='sub_4da1c':
            import ipdb;
            ipdb.set_trace()
            pass 
        '''
        
        
        '''
        write_dot(state.dep_graph.transitive_closure(ff), "zz.dot")
        os.system("dot -Tsvg -o strcpy.svg zz.dot")
        import ipdb;
        ipdb.set_trace()
        pass
       
        '''
        
        
        
        try:
            if function.name in ["strcpy","strcat"] or is_tainted_falg:
                def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
                def_explorer.set_current_state(state)
                def_explorer.set_current_codeloc(codeloc)
                def_explorer.set_RDA_handler(self)
                def_explorer.set_current_fucntion(self.cur_fun)
                backtrack_definations(def_explorer, reg_defs=[ff], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr)#function.addr)
                # with open(f"{self.cur_fun.name}.json","a+") as f:
                #     json.dump(
                #         {
                #             'function':function.name,
                #             'block_addr':state.current_codeloc.block_addr,
                #             'blk_statements_args':blk.statements[-1].args,
                #             'd3_length':length
                #         },f
                #     )
        except Exception as e:
            print("error 1628 ",e)
            raise e
            #raise e
        

        
        return True, state

        # return True, state, visited_blocks, dependency_graph

    def handle_strcpy(self, state, codeloc):
        # print('I am inside strcpy handleer')
        function = self._analysis.project.kb.functions.function(name="strcpy")
        # function.calling_convention = SimCC(self._analysis.project.arch)
        return self.handle_strcpy_xx(function, state, codeloc)

    def handle_strncpy(self, state, codeloc):

        function = self._analysis.project.kb.functions.function(name="strncpy")
        # print(" inside ", function.demangled_name)
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        return self.handle_strcpy_xx(function, state, codeloc)
    
    
    
    def handle_strlcpy(self, state, codeloc):
        # print('I am inside strcpy handleer')
        function = self._analysis.project.kb.functions.function(name="strlcpy")
        return self.handle_strcpy_xx(function, state, codeloc)
    
    def handle_strlcat(self, state, codeloc):
        # print('I am inside strcpy handleer')
        function = self._analysis.project.kb.functions.function(name="strlcat")
        return self.handle_strcpy_xx(function, state, codeloc)
    

    def handle_webGetVarString(self,state, codeloc):
        function = self._analysis.project.kb.functions.function(name="webGetVarString")
        print(" inside ->", function.name)
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)

        # magic_graph_print(state.dep_graph.transitive_closure(a0))
        if d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
            d0=d1 

        tags_2 = {ReturnValueTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        #data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
        #mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags_2)
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(d0, new_rax)
        state.dep_graph.add_edge(d1, new_rax)

        state.add_use_by_def(d0, d0.codeloc, None)
        state.add_use_by_def(d1, d1.codeloc, None)
        
        return True, state
    
    def xx_handle_find_val(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="find_val")
        
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)

        # magic_graph_print(state.dep_graph.transitive_closure(a0))
        #if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
            

        tags_2 = {ReturnValueTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        #data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
        #mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags_2)
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(d0, new_rax)
        state.dep_graph.add_edge(d1, new_rax)

        state.add_use_by_def(d0, d0.codeloc, None)
        state.add_use_by_def(d1, d1.codeloc, None)
        
        
        return True,state

    # get_cgi
    def handle_get_cgi_xx(self, function, state, codeloc, position=0):
        print(" inside ->", function.name)
        
        
        d0 = self.get_def_from_parameter(function, parameter_position=position, state=state)
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        #return True, state
        
        
        #print("for deb  
        #print(blk.statements[-1])
        
        
        #return True, state
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        
        getenv_counter[0]+=1
        
        
        # address this issue nvram_get(0x1, "Radio58On")
        if function.name== "nvram_get" and  len(function.arguments)==2 and d0.codeloc.ins_addr  not in self.cfg.insn_addr_to_memory_data :
            d0 = self.get_def_from_parameter(function, parameter_position=1, state=state)
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
        
        
        
        # to fix sitations :
        '''
            uVar3 = FUN_0040e898(&local_1a8,"ifname",acStack524);
            uVar3 = nvram_safe_get(uVar3);  --> this isse
            getIfIpv6addr(uVar3,auStack396,&local_8c);
            sprintf(acStack524,"ip -6 r del %s/%d  dev %s",auStack396,local_8c,uVar3);
            twsystem(acStack524,1);
        '''
        
        '''
                    To fix isse  e.g Tenda Ac15 @ http fnction=sub_3cb60
                    sprintf(acStack284,"wl%d_ifname",local_14);
                    local_1c = bcm_nvram_get(acStack284);
                    doSystemCmd(" td_acs_dbg -i %s  auto_bandwidth_measure 5",local_1c);
        '''
        
        
        
        
        
        
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        
        
        # to solve local variable 'tags_2' referenced before assignment
        
        token=""
        tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        if  d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
            bb1=self.cfg.insn_addr_to_memory_data[d0.codeloc.ins_addr]
            i=0
            while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                i+=1
            token=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
            
            if len(token)==0:
                arg=blk.statements[-1].args[0]
                if hasattr(arg,'reg_offset') :
                    for smt in blk.statements:
                        if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name'] == state.arch.register_names[d0.atom.reg_offset] and type(smt.src) == ailment.expression.Const:
                            i=0
                            while str(self.cfg.project.loader.memory.load(smt.src.value, i))[i+1] != '\\':
                                  i+=1
                            token=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                            print("Did I arrived here")
                            break
                                
                                
            
            
            
            tags_2 = {ReturnValueTag(function=function.addr,metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':token})} 
            print(" d0 in salt")
            #import ipdb;
            #ipdb.set_trace()
            #pass
        elif  not d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
            pred=[d for d in state.dep_graph.predecessors(d0)]
            if len(pred)==1 and type(pred[0].atom)!=MemoryLocation: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                #state.dep_graph.transitive_closure(d0)
                pred=[d for d in state.dep_graph.predecessors(pred[0])]
                for defination in pred :
                    if type(defination.atom)==MemoryLocation  and 'readonly' in  f'{defination}' :
                        i=0
                        while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                            i+=1
                        token=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]
                        tags_2 = {ReturnValueTag(function=function.addr,metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':token})} 
                        print(" fixing the salt")
                        break
                        
            elif len(pred)>=1:
                for defination in pred :
                    if defination.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:
                        tags_2=defination.tags
                        #d0.tags.update(tags_2)
                        d0= defination
                        #print("got gold here")
                        #write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
                        #os.system("dot -Tsvg -o getenv.svg zz.dot")
                        #import ipdb;
                        #ipdb.set_trace()
                        #pass
                        break
                    
                    elif  type(defination.atom)==MemoryLocation:
                        curr_tag = (defination.tags.copy()).pop()
                        if curr_tag.function is  not None and 'token' in curr_tag.metadata :
                            token=curr_tag.metadata['token']
                            tags_2 = {ReturnValueTag(function=function.addr,metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':token})}
                            print("got gold there")
                            break
                            
                        
                        
                        
            else:
                tags_2 = {ReturnValueTag(function=function.addr,metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':token})}
                
            
        
        
        else:
            tags_2 = {ReturnValueTag(
                function=function.addr,
                metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
            #atom = Register(16, 4)
        
       
        
        
        
        if 1==1 and token=="" and hasattr(blk,"statements") and len(blk.statements) >0 :
            for smt in blk.statements :
                if type(smt) == ailment.statement.Assignment and type(smt.dst) == ailment.expression.Register and  smt.dst.tags['reg_name']== state.arch.register_names[d0.atom.reg_offset] and type(smt.src)==ailment.expression.Const:
                    i=0
                    try:
                        while str(self.cfg.project.loader.memory.load(smt.src.value, i+1))[i+1] != '\\':
                            i+=1
                    except Exception as e:
                        i-=1
                        dddd=0
                    token=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                    tags_2 = {ReturnValueTag(function=function.addr,metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':token})} 
                    print("furthor fix")
                    break
            
        
        
        
        
        
        if token=="":
            token=self.get_stringby_use_def(d0,state)
            tags_2 = {ReturnValueTag(function=function.addr,metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr, 'token':token})} 
        
        if 1==0 and token=="":
            try:
                arg=blk.statements[-1].args[0]
                if hasattr(arg,'reg_offset') :
                    for smt in blk.statements:
                        if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name'] == state.arch.register_names[d0.atom.reg_offset] and type(smt.src) == ailment.expression.Const:
                            i=0
                            while str(self.cfg.project.loader.memory.load(smt.src.value, i))[i+1] != '\\':
                                  i+=1
                            token=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                            print("Did I arrived here")
                            break
            except Exception as e:
                print(e , " error at 2575")
        
        
        
        
        
        if d0.atom == atom:  #For ARM architecture
            d0.tags.update(tags_2)
            new_rax=d0
        
        
        
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        
        
        '''
        if token=="" and function.name=="sub_1d170" :#"getenv" :# and getenv_counter[0]==2:
            import ipdb;
            ipdb.set_trace()
            pass
            
        '''
        
        
        
        '''
        if function.name =="nvram_safe_get" :
            write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
            os.system("dot -Tsvg -o ss_nvram_safe_get.svg zz.dot")
            import ipdb;
            ipdb.set_trace()
            pass
        '''
        
        
        #print("we reach getenv here")
        '''
        if function.name =="getenv"  and token=="":
            write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
            os.system("dot -Tsvg -o getenv.svg zz.dot")
            import ipdb;
            ipdb.set_trace()
            pass
        '''
        
        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
        
        try:
            #mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
            mv = state.kill_and_add_definition(atom, state.current_codeloc, data, tags=tags_2)
        except Exception as e:
            print("error in 2006")
            print(e)
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
            
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(d0,new_rax)
        d0.tags.update(tags_2)
        new_rax.tags.update(tags_2)

        state.add_use_by_def(d0, d0.codeloc, None)
        print("token -> ",token)
        print("new_rax \n",new_rax)
        print("tags_2\n")
        print(tags_2)
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        '''
        if function.name=="bcm_nvram_get":
            import ipdb;
            ipdb.set_trace()
            pass
            
        '''
        
        
        
        '''
        if function.name =="nvram_safe_get" :
            write_dot(state.dep_graph.transitive_closure(new_rax), "zz.dot")
            os.system("dot -Tsvg -o ss_nvram_safe_get.svg zz.dot")
            import ipdb;
            ipdb.set_trace()
            pass
        '''
        
        return True, state
        
        
        
    # apears in rv130_v44_httpd    
    def handle_sub_1d170(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="sub_1d170")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)    
    
    def handle_get_cgi(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="get_cgi")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_nvram_default_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="nvram_default_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_nvram_pf_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="nvram_pf_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_acosNvramConfig_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="acosNvramConfig_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_config_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="config_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_uciGet(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="uciGet")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_entry(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="entry")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_wpa_config_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="wpa_config_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_httpGenListDataGet(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="httpGenListDataGet")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_wpa_config_set(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="wpa_config_set")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_vici_find_str(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="vici_find_str")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_DoHardwareComponent(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="DoHardwareComponent")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_device_get_string_value(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="device_get_string_value")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_cJSON_Parse(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="cJSON_Parse")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_OM_ValGet(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="OM_ValGet")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_acosUciConfig_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="acosUciConfig_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_OM_ValFind(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="OM_ValFind")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_get_parameter(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="get_parameter")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_get_wlan_setting(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="get_wlan_setting")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_av_dict_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="av_dict_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_cgi_value(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="cgi_value")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_stringOut(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="stringOut")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_cJSON_GetObjectItem(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="cJSON_GetObjectItem")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_sw_getValueByName(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="sw_getValueByName")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_querystr(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="querystr")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_find_val(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="find_val")  
        return self.handle_get_cgi_xx(function, state, codeloc,1)
    def handle_log_query(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="log_query")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_value_parser_by_index_D7000(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="value_parser_by_index_D7000")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_getoption(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="getoption")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_WEB_GetVar(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="WEB_GetVar")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_av_opt_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="av_opt_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_paramValueFromObjGet(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="paramValueFromObjGet")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_help_getObjPtr(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="help_getObjPtr")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_NCONF_get_string(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="NCONF_get_string")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_av_metadata_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="av_metadata_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_httpGetEnv(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="httpGetEnv")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_nvram_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="nvram_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    def handle_config_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="config_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    
    # nvram_safe_get
    def handle_nvram_safe_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="nvram_safe_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    
    def handle_bcm_nvram_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="bcm_nvram_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    
    def handle_getenv(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="getenv")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    
    def handle_nvram_default_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="nvram_default_get")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    
    def handle_gets(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="gets")  
        return self.handle_get_cgi_xx(function, state, codeloc,0)
        
        
    def handle_fgets(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="fgets")
        #return self.handle_get_cgi_xx(function, state, codeloc,0)
        

        cc = function.calling_convention

        parameter_position = 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        parameter_position_1 = 1
        parameter_atom_1 = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position_1], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        # in the future  we need to check if there is a third parameter or not
        parameter_position_2 = 2
        parameter_atom_2 = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position_2], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]

        def1 = state.get_definitions(parameter_atom_2)
        d2 = [d for d in def1][0]
        
        '''
        blk=self.get_clinic_block(self.clinic,d0.codeloc.block_addr)
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        
        ff=self.get_memory_defination(d0,function,state,codeloc)

        tags_2 = {ReturnValueTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        #atom = Register(16, 4)
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        
        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
        mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(new_rax,ff)

        state.add_use_by_def(new_rax, d0.codeloc, None)
        
        
        ''' 
        write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
        os.system("dot -Tsvg -o ss.svg zz.dot")
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        return True, state
        
    def handle_recv(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="recv")
        return self.handle_get_cgi_xx(function, state, codeloc,1)
        
        
    def handle_recvfrom(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="recvfrom")
        return self.handle_get_cgi_xx(function, state, codeloc,1)
        
    def handle_recvmsg(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="recvmsg")
        return self.handle_get_cgi_xx(function, state, codeloc,1)
        
        
    def handle_recvmmsg(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="recvmmsg")
        return self.handle_get_cgi_xx(function, state, codeloc,1)
        
    def handle_websGetVar(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="websGetVar")
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        return  self.process_sub_42a978(function, state, codeloc, d1)
        #return x,a_state
        #return self.handle_get_cgi_xx(function, state, codeloc,2)
        
    #acosNvramConfig_read("wan_ifname",auStack92,0x20)    FUN_00024408(void)
    def handle_acosNvramConfig_read(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="acosNvramConfig_read")
        d1 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
         
            if type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >0 :
                arg0=call_statement.args[1] 
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    bb=""
                    if self.dec is not None:
                        xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                        bb=xx.split('"')[1]
                    
                    
                    tags = {ReturnValueTag(
                        function=function.addr,
                        metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb})}

                    data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)

                    # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

                    tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                    # state.add_use(atom, tmp_codeloc)
                    mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                    ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                    #ff = [d for d in ff_defs][0]
                    ff=next( iter(ff_defs) )
                    
                    
                    
                    state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)
                    #state.add_use_by_def(d1, d1.codeloc, None)
                    
                    
                    '''
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    '''
                    

                    return True, state
        #return  self.process_sub_42a978(function, state, codeloc, d1)
    
    def handle_json_object_object_get_ex(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="json_object_object_get_ex")
        return self.handle_get_cgi_xx(function, state, codeloc,2)
         
        
        
    def handle_nvram_set_xx(self,function, state, codeloc,function_name):  # state, codeloc, function):
        #function = self._analysis.project.kb.functions.function(name="nvram_set")
        #function_name=function.name
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        print(" inside -> ",function.name)
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state,blk=blk)
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state,blk=blk)
        
        if d0 is None or d1 is None:
             return True, state
            
        
        
        d0_token=""
        d1_constantCheckFlag=False
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            try:
                if type(call_statement) == ailment.statement.Call :
                    if hasattr(call_statement,"args") and  call_statement.args is not None and len(call_statement.args) >0 and 'reference_variable'  not in call_statement.args[1].tags :
                        d1_constantCheckFlag=True
                    else:
                        return True, state 

                    if self.dec is not None and (call_statement,False) in self.dec.codegen.ailexpr2cnode:
                        xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                        if 'reference_variable'   in call_statement.args[0].tags :
                            d0_token=xx.split('"')[1]
                            
            except Exception as e:
                d1_constantCheckFlag=False
                
        
        
        
        
       
        ## if stored is not a value recieved from the user; the flag her in case the defination address us wrongly regrence a memory, we used clinic to make sure earlier
        if not d1_constantCheckFlag and d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
            return True, state    
        
        
        print("d0_token ->",d0_token)
        '''
        if "soapc_base_C" == d0_token:
            
            import ipdb;
            ipdb.set_trace()
            pass
           
        '''
        print("---------- Start Nvram_set ----------")
        def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
        def_explorer.set_d0(d0)
        if d0_token!="":
            def_explorer.set_d0_token(d0_token)
        def_explorer.set_d1(d1)
        def_explorer.set_transitive_funtion_name(function_name)
        
        
        
        def_explorer.set_current_codeloc(codeloc)
        def_explorer.set_current_fucntion(self.cur_fun)
        def_explorer.set_current_state(state)
        def_explorer.set_RDA_handler(self)

        backtrack_definations(def_explorer, reg_defs=[d1], result_file=self.get_get2set_file(),
                              memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function_name,#function.name,
                              memcpy_addr=state.current_codeloc.ins_addr)
        print("---------- End Nvram_set ----------")

        #'''
        #magic_graph_print(state.dep_graph.transitive_closure(d0))
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        

        return True, state
    
    def handle_nvram_set(self, state, codeloc):  # state, codeloc, function):
        function_name="nvram_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_SetValue(self, state, codeloc):  # state, codeloc, function):
        function_name="SetValue"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_config_set(self, state, codeloc):  # state, codeloc, function):
        function_name="config_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    
    def handle_setenv(self, state, codeloc):  # state, codeloc, function):
        function_name="setenv"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_nvram_safe_set(self, state, codeloc):  # state, codeloc, function):
        function_name="nvram_safe_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_nvram_pf_set(self, state, codeloc):  # state, codeloc, function):
        function_name="nvram_pf_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_artblock_set(self, state, codeloc):  # state, codeloc, function):
        function_name="artblock_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_artblock_set(self, state, codeloc):  # state, codeloc, function):
        function_name="artblock_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_acos_nvram_set(self, state, codeloc):  # state, codeloc, function)
        function_name="acos_nvram_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_acosNvramConfig_set(self, state, codeloc):  # state, codeloc, function):
        function_name="acosNvramConfig_set"
        print("inside -> ",function_name)
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_acosNvramConfig_write(self, state, codeloc):  # state, codeloc, function):
        function_name="acosNvramConfig_write"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_envz_add(self, state, codeloc):  # state, codeloc, function):
        function_name="envz_add"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_config_set(self, state, codeloc):  # state, codeloc, function):
        function_name="config_set"
        function = self._analysis.project.kb.functions.function()
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_uciSet(self, state, codeloc):  # state, codeloc, function):
        function_name="uciSet"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_device_set_string_value(self, state, codeloc):  # state, codeloc, function):=
        function_name="device_set_string_value"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_wpa_config_set(self, state, codeloc):  # state, codeloc, function):
        function_name="wpa_config_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_scfgmgr_set_by_index_D7000(self, state, codeloc):  # state, codeloc, function):=
        function_name="scfgmgr_set_by_index_D7000"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_acosUciConfig_set(self, state, codeloc):  # state, codeloc, function):
        function_name="acosUciConfig_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_OM_ValSet(self, state, codeloc):  # state, codeloc, function):
        function_name="OM_ValSet"
        function = self._analysis.project.kb.functions.function(name="OM_ValSet")
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    def handle_CAL_abstract_set(self, state, codeloc):  # state, codeloc, function):
        function_name="CAL_abstract_set"
        function = self._analysis.project.kb.functions.function(name=function_name)
        return self.handle_nvram_set_xx(function, state, codeloc,function_name)
    
    
        
        

    def handle_malloc_xx(self, function, state, codeloc):
        # print("codeloc -> ",codeloc, "func_addr ->",hex(function.addr))   state.current_codeloc.
        # function = self._analysis.project.kb.functions.function(codeloc.block_addr)
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        print("inside ", function.name)
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        # pcd0 = state.dep_graph.predecessors(d0)
        # print(" \n rdi predesseors")
        rdi_mmm = None
        
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]

        # print("----------------------")
        #defs = state.get_definitions(Register(24, size=state.arch.bytes))  # state.arch.bytes =4 f0r 86 and =4 for MIPS
        #a0 = [d for d in defs][0]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        '''
        try:
            defs = state.get_definitions(Register(ret_register_name_size[0], ret_register_name_size[1]))  # state.arch.bytes =4 f0r 86 and =4 for MIPS
            v0 = [d for d in defs][0]
        except Exception as e:
            import ipdb;
            ipdb.set_trace()
            pass
        #atom = Register(16, size=state.arch.bytes)
        '''
       

        # magic_graph_print(state.dep_graph.transitive_closure(a0))

        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''

        tags = {ReturnValueTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        mv = state.kill_and_add_definition(atom, d0.codeloc,
                                           MultiValues(state.top(atom.size * state.arch.byte_width)),
                                           tags=tags)  # it was codeloc

        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        ff = [d for d in ff_defs][0]

        # print("d0 again")
        # print(d0)

        state.dep_graph.add_edge(d0, ff)

        # magic_graph_print(state.dep_graph.transitive_closure(ff))
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''

        return True, state 

    def handle_malloc(self, state, codeloc):
        # print("--------\n","inside malloc")
        function = self._analysis.project.kb.functions.function(name="malloc")
        # print(" inside ", function.demangled_name)
        return self.handle_malloc_xx(function, state, codeloc)
    
    def handle_strtok(self, state, codeloc):
        # print("--------\n","inside malloc")
        function = self._analysis.project.kb.functions.function(name="strtok")
        # print(" inside ", function.demangled_name)
        return self.handle_malloc_xx(function, state, codeloc)

    
    def handle_strtok_r(self, state, codeloc):
        # print("--------\n","inside malloc")
        function = self._analysis.project.kb.functions.function(name="strtok")
        # print(" inside ", function.demangled_name)
        return self.handle_malloc_xx(function, state, codeloc)
    
    def handle_realloc(self, state, codeloc):
        # print("--------\n","inside realloc")
        function = self._analysis.project.kb.functions.function(name="realloc")
        return self.handle_malloc_xx(function, state, codeloc)

    def handle_strlen(self, state, codeloc):
        # print("--------\n","inside strlen")
        function = self._analysis.project.kb.functions.function(name="strlen")
        print(" inside ", function.demangled_name)
        cc = function.calling_convention

        parameter_position = 0
        parameter_atom = Atom.from_argument(
            SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
            self._analysis.project.arch.registers
        )

        def0 = state.get_definitions(parameter_atom)
        d0 = [d for d in def0][0]
        #write_dot(state.dep_graph.transitive_closure(d0), "zz.dot")
        #os.system("dot -Tsvg -o strlen.svg zz.dot")
        '''
       
        
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        #atom= d0.atom
        '''
        try:
            blk=self.get_clinic_block(self.clinic,d0.codeloc.block_addr)
            arg0=blk.statements[0].args[0]
            if hasattr(arg0,'base') :
                atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)

            else:
                atom= d0.atom
        except Exception as e:
            print(e)
            atom= d0.atom
        '''
            

        tags = {SideEffectTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}

       

        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)

        tags_2 = {ReturnValueTag(
            function=function.addr,
            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        #atom = Register(16, 4)
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        
        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
        mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(d0, new_rax)

        state.add_use_by_def(d0, d0.codeloc, None)

        return True, state

    def handle_strcat(self, state, codeloc):

        # print("inside strcat")
        # return True, state
        function = self._analysis.project.kb.functions.function(name="strcat")
        # print(" inside ", function.demangled_name)
        return self.handle_strcpy_xx(function, state, codeloc)

    def handle_strncat(self, state, codeloc):
        # print("inside strncat")
        # return True, state
        function = self._analysis.project.kb.functions.function(name="strncat")

        return self.handle_strcpy_xx(function, state, codeloc)
    
    def handle_memcpy(self, state, codeloc):        # print("inside memcpy")
        function = self._analysis.project.kb.functions.function(name="memcpy")
        # print(" inside ", function.demangled_name)
        return self.handle_strcpy_xx(function, state, codeloc)
    
    def handle_memmove(self, state, codeloc):
        # print("inside memcpy")
        function = self._analysis.project.kb.functions.function(name="memmove")
        # print(" inside ", function.demangled_name)
        return self.handle_strcpy_xx(function, state, codeloc)
    
    def handle_indirect_call(self, state:"ReachingDefinitionsState", src_codeloc: Optional["CodeLocation"] = None) :
        """
        The RDA encountered a function call with multiple possible values, or TOP as a target
        :param state:
        :param src_codeloc:
        :return:
        """
        
        print("inside indirect", src_codeloc )
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        function=None
        recovered_functions=[]
        blk=self.get_clinic_block(self.clinic,src_codeloc.block_addr)
        print(blk.statements[-1])
        
        
        if 1==0 and  abs(src_codeloc.ins_addr -int(0x40a5d4)) <8:
            
            import ipdb;
            ipdb.set_trace()
            pass
        
        
        if hasattr(blk,'statements') and hasattr(blk.statements[-1],'target') and  hasattr(blk.statements[-1].target,'value'):
            try:
                function=self.cfg.functions.get_by_addr(addr=blk.statements[-1].target.value)
                print(" handeled in indirect way-->",function.name)
                recovered_functions.append(function)
                if 1==0 and  function.name=="sub_40a424":
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    
            except Exception as e:
                print("can not recover the function")
                print(blk.statements[-1])
                return True, state
            
        elif hasattr(blk,'statements') and (blk.statements[-1],'target') and type(blk.statements[-1].target)==ailment.expression.Register:
            #return True, state
            if  blk.statements[-1].target.reg_offset== state.arch.registers['t9'][0]: #216:
                defs=state.tmp_definitions[0].copy()
                while len (defs)>0:
                    recovered_functions=recovered_functions+self.get_functionAddress_by_use_def(defs.pop(),state)
                    
                recovered_functions=list(set(recovered_functions))
                #tmp_state=state.copy()
        else:
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
            flag=False
            
            for i in state.tmp_definitions.keys():
                dd=state.tmp_definitions[i].copy().pop()
                if type(dd.atom)==Register and dd.atom.reg_offset==state.arch.registers['t9'][0]:
                    flag=True
                    break
                            
            if  flag:
                defs=state.tmp_definitions[i].copy() 
                while len (defs)>0:
                    recovered_functions=recovered_functions+self.get_functionAddress_by_use_def(defs.pop(),state)
                recovered_functions=list(set(recovered_functions))
                if len(recovered_functions)>0 :
                    print(" did something useful")
                    
                
        
        
        
        
        
        #'''
        if len(recovered_functions)>0 :# is not None:
            if len(recovered_functions)==1:    
                function=recovered_functions[0]
                try:
                    flag,state, *rest = self.handle_local_function(state,function.addr,0,5,self._analysis.visited_blocks,self._analysis.dep_graph,src_codeloc.ins_addr, src_codeloc)
                except Exception as e:
                    return True, state
                return flag, state
            
            else:
                
                for function in recovered_functions:
                    tmp_state=state.copy()
                    try:
                        flag,state, *rest = self.handle_local_function(tmp_state,function.addr,0,5,self._analysis.visited_blocks,self._analysis.dep_graph,src_codeloc.ins_addr, src_codeloc)
                    except Exception as e:
                        print("error at 3564 ",e)
                    
                    
                    
        
        return True, state
        #'''
        function_name=function.name
        
        
        
        
        #print("blk inside indirect ", blk.statements[-1])
        
        func = getattr(MyHandler, 'handle_{}'.format(function_name), None)
        if func is not None :
            print(" handeled in indirect way-->",function_name)
            self.handle_local_function(state,function.addr,0,5,self._analysis.visited_blocks,self._analysis.dep_graph,src_codeloc.ins_addr, src_codeloc)
            flag,state=func(self, state, src_codeloc)
            return flag, state
            
            #return True,state, visited_blocks, dependency_graph
        
        
        
        
        if function is None:
            return True, state  
        else:
            return True, state 
            import ipdb;
            ipdb.set_trace()
            pass
            
        
        project=self._analysis.project
        manager = ailment.Manager(arch=project.arch)
        block = project.factory.block(src_codeloc.block_addr)
        ail_block = ailment.IRSBConverter.convert(block.vex, manager)
        simp = project.analyses.AILBlockSimplifier(ail_block,  self.cur_fun.addr)
        csm = project.analyses.AILCallSiteMaker(simp.result_block)

        if csm.result_block:
            ail_block = csm.result_block
            simp = project.analyses.AILBlockSimplifier(ail_block,  self.cur_fun.addr)
        simp.result_block
        call_target=simp.result_block.statements[-1].target
        if self.cfg.functions.contains_addr(call_target) :
            function = self.cfg.functions.get_by_addr(call_target)
            print(func.name, "  inside in direct")
        
            import ipdb;
            ipdb.set_trace()
            pass
        
        return False, state    
    
    
    def handle_sub_42af24(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="sub_42af24")  
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        return self.handle_get_cgi_xx(function, state, codeloc,0)
    
    
    
    def handle_GetValue(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="GetValue")  
        #GetValue("dhcps.en",acStack84); from httpd inside Tenda Ac15  FUN_0003a30c(void)
        # i make it d1 instead of d0 because I copied code from the other places
        d1 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            if type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >1 :
                arg0=call_statement.args[1] 
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    bb=""
                    '''
                    if self.dec is not None:
                        xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                        bb=xx.split('"')[1]
                    '''
                    
                    #d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
                    if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:                        
                        pred=[d for d in state.dep_graph.predecessors(d1)]
                        '''
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        bb=""
                        if len(pred)==1 and type(pred[0].atom)!=MemoryLocation: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                            pred=[d for d in state.dep_graph.predecessors(pred[0])]
                        for defination in pred :
                                if type(defination.atom)==MemoryLocation  and 'readonly' in  f'{defination}' :
                                    i=0
                                    while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                          i+=1
                                    bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]                                    
                                    break
                        
                    
                    
                    
                    
                    tags = {ReturnValueTag(
                        function=function.addr,
                        metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb})}

                    data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)

                    # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

                    tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                    # state.add_use(atom, tmp_codeloc)
                    #mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                    try:
                        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                    except Exception as e:
                        missing_def = Definition(atom, state.current_codeloc)
                        val =bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                        data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, len(bb) * state.arch.byte_width), missing_def) )
                        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                    
                    
                    ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                    #ff = [d for d in ff_defs][0]
                    ff=next( iter(ff_defs) )
                    
                    
                    
                    state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)
                    '''
                    if bb== "lan.gst.1.ip":
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    
                    '''
        return True, state
    
    
    
    #FUN_0001de00(acStack1319,uVar5,param_2); in rv130_v44, it is a wrapper, inside it there is either  BIO_gets  or fgets
    def handle_sub_1de00(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="sub_1de00") 
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        
        
        #arg0=blk.statements[-1].args[1] 
        
        d1 = self.get_def_from_parameter(function, parameter_position=0, state=state) # I used d0 just not to modify in the code
        d2 = self.get_def_from_parameter(function, parameter_position=1, state=state)
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            print("call_statement -> ", call_statement)
            if type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >2 :
                arg0=call_statement.args[0] 
                
                if  type(arg0) == ailment.expression.Const and hasattr(arg0,"value")  :
                    ff= None
                    ff_list=[]
                    for node in state.dep_graph.nodes():
                        if isinstance(node.atom, MemoryLocation) and node.atom.addr==arg0.value:
                            if node not in ff_list:
                                ff_list.append(node)
                            ff= node
                            #print(node)
                            #print(" \n #### \n  #######\n")
                            #break
                        
                        if len(ff_list)==2 and ff_list[0].atom.addr== ff_list[1].atom.addr:
                            ff= ff_list[0] if ff_list[0].size > ff_list[1].size else ff_list[1] 
                            
                        
                        elif len(ff_list)>1:
                                pred=[d for d in state.dep_graph.predecessors(d2)]
                                if len(pred)==1 and type(pred[0].atom)!=Register: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                                    #state.dep_graph.transitive_closure(d0)
                                    pred=[d for d in state.dep_graph.predecessors(pred[0])]
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation :
                                            for GF in ff_list:
                                                if GF.atom.addr==  defination.atom.addr and defination.size ==GF.size:
                                                    ff=GF
                                                    break
                                else:
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation :
                                            for GF in ff_list:
                                                if GF.atom.addr==  defination.atom.addr and defination.size ==GF.size:
                                                    ff=GF
                                                    break
                                    
                                                
                    
                    if 1==1:
                        bb=""
                        if self.dec is not None:
                            xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                            if '"' in xx:
                                bb=xx.split('"')[1]
                            else:
                                pred=[d for d in state.dep_graph.predecessors(d1)]
                                if len(pred)==1 and type(pred[0].atom)!=MemoryLocation: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                                    #state.dep_graph.transitive_closure(d0)
                                    pred=[d for d in state.dep_graph.predecessors(pred[0])]
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation  and 'readonly' in  f'{defination}' :
                                            i=0
                                            while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                                i+=1
                                            bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]
                                

                        print(bb," \n --- \n  ----\n")
                        length=-1
                        if type(blk.statements[-1].args[2]) ==ailment.expression.Const :
                                length=blk.statements[-1].args[2].value

                        tags = {ReturnValueTag(
                            function=function.addr,
                            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length, 'ins_addr': state.current_codeloc.ins_addr })}
                        
                    if 1==0 and ff is not None and bb=="RadvdList":
                        import ipdb;
                        ipdb.set_trace()
                        pass 
                    
                    
                    if 1==0 and ff is None and bb=="RoutingList":
                        import ipdb;
                        ipdb.set_trace()
                        pass 
                    
                    if ff  is None:
                        print( " could not find the public varabile in graph")
                        
                        block_addr=blk.addr
                        project=self._analysis.project
                        manager = ailment.Manager(arch=project.arch)
                        block = project.factory.block(block_addr)

                        for stmt in block.vex.statements:
                            if hasattr(stmt,'offset') and state.arch.register_names[stmt.offset]==state.arch.register_names[d2.atom.reg_offset]:#'a1':
                                break

                        addr = arg0.value#self._expr(stmt.addr)
                        size = stmt.data.result_size(block.vex.tyenv) // 8
                        bits = stmt.data.result_size(block.vex.tyenv)
                        top = state.top(bits)
                        data = MultiValues(top)
                        temp_codeloc=CodeLocation(block.addr, stmt.tag_int, d1.codeloc.ins_addr,context=None,)
                        atom = MemoryLocation(arg0.value,size)
                        mv=state.kill_and_add_definition(atom, temp_codeloc, data, tags=tags)
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        ff=next( iter(ff_defs) )
                        state.dep_graph.add_node(ff)
                        
                        pred=[d for d in state.dep_graph.predecessors(d2)]
                        if len(pred)>=1:
                            for defination in pred :
                                state.dep_graph.add_edge(ff,defination)

                        
                        
                        '''
                        for stmt in blk.statements:
                            if type(stmt) ==ailment.statement.Store and stmt.variable.addr ==arg0.value :
                                size= stmt.variable.size  #523272
                                atom = MemoryLocation(arg0.value,size)
                                bits =  size * state.arch.byte_width
                                top = state.top(bits)
                                dummy_atom =atom
                                def_ = Definition(dummy_atom, (state._subject.content.addr,)   )
                                top = state.annotate_with_def(top, def_)
                                state.add_memory_use_by_def(def_, state.current_codeloc  )
                                data: MultiValues  =  MultiValues(top)
                                mv = state.kill_and_add_definition(atom, (state._subject.content.addr,), data, tags=tags)
                                ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                                ff=next( iter(ff_defs) )
                                #print("New memory defination",ff)
                                state.dep_graph.add_node(ff)
                        '''
                    ff.tags.update(tags)
                    d1.tags.update(tags)
                    d2.tags.update(tags)
                    if ff not in state.dep_graph.nodes() :
                        state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)     
                    print(ff)
                    print(d1)
                    print(" \n #### \n  #######\n")
                    return True, state
         
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    
                    bb=""                    
                    length=-1
                    if type(blk.statements[-1].args[1]) ==ailment.expression.Const :
                            length=blk.statements[-1].args[1].value
                            
                    tags = {ReturnValueTag(
                        function=function.addr,
                        metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length})}

                    try:
                        #data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                        size= atom.size
                        bits =  size * state.arch.byte_width
                        top = state.top(bits)
                        dummy_atom =atom
                        def_ = Definition(atom, state.current_codeloc)#Definition(dummy_atom, (state._subject.content.addr,)   )
                        top = state.annotate_with_def(top, def_)
                        state.add_memory_use_by_def(def_, state.current_codeloc  )
                        data: MultiValues  =  MultiValues(top)
                    except Exception as e:
                        print("error 3698",e)
                        missing_def = Definition(atom, state.current_codeloc)
                        #val =arg0.bits #bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                        #data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, val * state.arch.byte_width), missing_def) )
                        #data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(523272, 523272* state.arch.byte_width, missing_def) )
                        val =bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                        data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, len(bb) * state.arch.byte_width), missing_def) )

                        # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

                    tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                    # state.add_use(atom, tmp_codeloc)
                    mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                    ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                    #ff = [d for d in ff_defs][0]
                    ff=next( iter(ff_defs) )
                    print("New memory defination",ff)
                    #print(function.has)
                    
                    state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)
                    ff.tags.update(tags)
                    d1.tags.update(tags)
                    
                    '''
                    snd_blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr,False)
                    parameter_atom=d1.atom
                    # to solve the issue when the genereated new defination can not be identified later for exapmple at sprintf where the other have of the fix have been introduced as well 
                    try:
                        
                        for smt in snd_blk.statements:
                                if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name']==state.arch.register_names[parameter_atom.reg_offset] :
                                    #print(smt)
                                    if type(smt.src)==ailment.expression.Register :
                                        defination_dictionary[smt.src.reg_offset]=ff
                                        print("we enter the Detour")
                                        break
                    
                    except Exception as e:
                        print(e)
                        print(smt)
                        print("the Detour fails &&&&&&&&&&&&&&&&7   \n")
                    '''
                    #state.add_use_by_def(d1, d1.codeloc, None)
                    
                    try:
                        ret_register_name=state.arch.register_names[state.arch.ret_offset]
                        ret_register_name_size=state.arch.registers[ret_register_name]
                        ret_atom = Register(ret_register_name_size[0], ret_register_name_size[1])
                        mv = state.kill_and_add_definition(ret_atom, d1.codeloc, data, tags=tags)#tags_2)
                        
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        state.dep_graph.add_edge(ff,new_rax)
                        if function.name not in New_input_getters:
                            New_input_getters.append(function.name)
                            
                        #write_dot(state.dep_graph.transitive_closure(new_rax), "zz.dot")
                        #os.system(f'dot -Tsvg -o {function.name}.svg zz.dot')
                        
                    except Exception as e:
                        print(e)
                        #raise(e)
                    
                    return True, state
                
         
    
    
    #   NK_query_entry_get("logout",acStack96,0x3c,0)
    def handle_NK_query_entry_get(self, state, codeloc):
        function = self._analysis.project.kb.functions.function(name="NK_query_entry_get") 
        
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        
        
        #arg0=blk.statements[-1].args[1] 
        
        d1 = self.get_def_from_parameter(function, parameter_position=0, state=state) # I used d0 just not to modify in the code
        d2 = self.get_def_from_parameter(function, parameter_position=1, state=state)
        '''
        import ipdb;
        ipdb.set_trace()
        pass    
        '''
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            print("call_statement -> ", call_statement)
            if type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >2 :
                arg0=call_statement.args[1] 
                
                if  type(arg0) == ailment.expression.Const and hasattr(arg0,"value")  :
                    ff= None
                    ff_list=[]
                    for node in state.dep_graph.nodes():
                        if isinstance(node.atom, MemoryLocation) and node.atom.addr==arg0.value:
                            if node not in ff_list:
                                ff_list.append(node)
                            ff= node
                            #print(node)
                            #print(" \n #### \n  #######\n")
                            #break
                        
                        if len(ff_list)==2 and ff_list[0].atom.addr== ff_list[1].atom.addr:
                            ff= ff_list[0] if ff_list[0].size > ff_list[1].size else ff_list[1] 
                            
                        
                        elif len(ff_list)>1:
                                pred=[d for d in state.dep_graph.predecessors(d2)]
                                if len(pred)==1 and type(pred[0].atom)!=Register: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                                    #state.dep_graph.transitive_closure(d0)
                                    pred=[d for d in state.dep_graph.predecessors(pred[0])]
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation :
                                            for GF in ff_list:
                                                if GF.atom.addr==  defination.atom.addr and defination.size ==GF.size:
                                                    ff=GF
                                                    break
                                else:
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation :
                                            for GF in ff_list:
                                                if GF.atom.addr==  defination.atom.addr and defination.size ==GF.size:
                                                    ff=GF
                                                    break
                                    
                                                
                    
                    if 1==1:
                        bb=""
                        if self.dec is not None:
                            xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                            if '"' in xx:
                                bb=xx.split('"')[1]
                            else:
                                pred=[d for d in state.dep_graph.predecessors(d1)]
                                if len(pred)==1 and type(pred[0].atom)!=MemoryLocation: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                                    #state.dep_graph.transitive_closure(d0)
                                    pred=[d for d in state.dep_graph.predecessors(pred[0])]
                                    for defination in pred :
                                        if type(defination.atom)==MemoryLocation  and 'readonly' in  f'{defination}' :
                                            i=0
                                            while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                                i+=1
                                            bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]
                                

                        print(bb," \n --- \n  ----\n")
                        length=-1
                        if type(blk.statements[-1].args[2]) ==ailment.expression.Const :
                                length=blk.statements[-1].args[2].value

                        tags = {ReturnValueTag(
                            function=function.addr,
                            metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length, 'ins_addr': state.current_codeloc.ins_addr })}
                        
                    if 1==0 and ff is not None and bb=="RadvdList":
                        import ipdb;
                        ipdb.set_trace()
                        pass 
                    
                    
                    if 1==0 and ff is None and bb=="RoutingList":
                        import ipdb;
                        ipdb.set_trace()
                        pass 
                    
                    if ff  is None:
                        print( " could not find the public varabile in graph")
                        
                        block_addr=blk.addr
                        project=self._analysis.project
                        manager = ailment.Manager(arch=project.arch)
                        block = project.factory.block(block_addr)

                        for stmt in block.vex.statements:
                            if hasattr(stmt,'offset') and state.arch.register_names[stmt.offset]==state.arch.register_names[d2.atom.reg_offset]:#'a1':
                                break

                        addr = arg0.value#self._expr(stmt.addr)
                        size = stmt.data.result_size(block.vex.tyenv) // 8
                        bits = stmt.data.result_size(block.vex.tyenv)
                        top = state.top(bits)
                        data = MultiValues(top)
                        temp_codeloc=CodeLocation(block.addr, stmt.tag_int, d1.codeloc.ins_addr,context=None,)
                        atom = MemoryLocation(arg0.value,size)
                        mv=state.kill_and_add_definition(atom, temp_codeloc, data, tags=tags)
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        ff=next( iter(ff_defs) )
                        state.dep_graph.add_node(ff)
                        
                        pred=[d for d in state.dep_graph.predecessors(d2)]
                        if len(pred)>=1:
                            for defination in pred :
                                state.dep_graph.add_edge(ff,defination)

                        
                        
                        '''
                        for stmt in blk.statements:
                            if type(stmt) ==ailment.statement.Store and stmt.variable.addr ==arg0.value :
                                size= stmt.variable.size  #523272
                                atom = MemoryLocation(arg0.value,size)
                                bits =  size * state.arch.byte_width
                                top = state.top(bits)
                                dummy_atom =atom
                                def_ = Definition(dummy_atom, (state._subject.content.addr,)   )
                                top = state.annotate_with_def(top, def_)
                                state.add_memory_use_by_def(def_, state.current_codeloc  )
                                data: MultiValues  =  MultiValues(top)
                                mv = state.kill_and_add_definition(atom, (state._subject.content.addr,), data, tags=tags)
                                ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                                ff=next( iter(ff_defs) )
                                #print("New memory defination",ff)
                                state.dep_graph.add_node(ff)
                        '''
                    ff.tags.update(tags)
                    d1.tags.update(tags)
                    d2.tags.update(tags)
                    if ff not in state.dep_graph.nodes() :
                        state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)     
                    print(ff)
                    print(d1)
                    print(" \n #### \n  #######\n")
                    return True, state
                
                
                
                '''
                import ipdb;
                ipdb.set_trace()
                pass    
                
                
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                elif type(arg0) == ailment.expression.Const and hasattr(arg0,"value"):
                    #atom = MemoryLocation( state.stack_address(arg0.value),4)
                    atom = MemoryLocation(arg0.value,arg0.bits)#523272)#
                '''
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    
                    bb=""
                    if self.dec is not None:
                        xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                        bb=xx.split('"')[1]
                     
                    print(bb," \n --- \n  ----\n")
                    ''' 
                    if bb== "nUser":
                        import ipdb;
                        ipdb.set_trace()
                        pass   
                    '''
                    length=-1
                    if type(blk.statements[-1].args[2]) ==ailment.expression.Const :
                            length=blk.statements[-1].args[2].value
                            
                    tags = {ReturnValueTag(
                        function=function.addr,
                        metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length})}

                    try:
                        #data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                        size= atom.size
                        bits =  size * state.arch.byte_width
                        top = state.top(bits)
                        dummy_atom =atom
                        def_ = Definition(atom, state.current_codeloc)#Definition(dummy_atom, (state._subject.content.addr,)   )
                        top = state.annotate_with_def(top, def_)
                        state.add_memory_use_by_def(def_, state.current_codeloc  )
                        data: MultiValues  =  MultiValues(top)
                    except Exception as e:
                        print("error 2841",e)
                        missing_def = Definition(atom, state.current_codeloc)
                        #val =arg0.bits #bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                        #data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, val * state.arch.byte_width), missing_def) )
                        #data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(523272, 523272* state.arch.byte_width, missing_def) )
                        val =bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                        data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, len(bb) * state.arch.byte_width), missing_def) )

                        # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

                    tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                    # state.add_use(atom, tmp_codeloc)
                    mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                    ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                    #ff = [d for d in ff_defs][0]
                    ff=next( iter(ff_defs) )
                    print("New memory defination",ff)
                    #print(function.has)
                    
                    state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)
                    ff.tags.update(tags)
                    d1.tags.update(tags)
                    
                    '''
                    snd_blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr,False)
                    parameter_atom=d1.atom
                    # to solve the issue when the genereated new defination can not be identified later for exapmple at sprintf where the other have of the fix have been introduced as well 
                    try:
                        
                        for smt in snd_blk.statements:
                                if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name']==state.arch.register_names[parameter_atom.reg_offset] :
                                    #print(smt)
                                    if type(smt.src)==ailment.expression.Register :
                                        defination_dictionary[smt.src.reg_offset]=ff
                                        print("we enter the Detour")
                                        break
                    
                    except Exception as e:
                        print(e)
                        print(smt)
                        print("the Detour fails &&&&&&&&&&&&&&&&7   \n")
                    '''
                    #state.add_use_by_def(d1, d1.codeloc, None)
                    
                    try:
                        ret_register_name=state.arch.register_names[state.arch.ret_offset]
                        ret_register_name_size=state.arch.registers[ret_register_name]
                        ret_atom = Register(ret_register_name_size[0], ret_register_name_size[1])
                        mv = state.kill_and_add_definition(ret_atom, d1.codeloc, data, tags=tags)#tags_2)
                        
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        state.dep_graph.add_edge(ff,new_rax)
                        if function.name not in New_input_getters:
                            New_input_getters.append(function.name)
                            
                        #write_dot(state.dep_graph.transitive_closure(new_rax), "zz.dot")
                        #os.system(f'dot -Tsvg -o {function.name}.svg zz.dot')
                        
                    except Exception as e:
                        print(e)
                        #raise(e)
                    
                    return True, state
        
    
    def get_simp_blk(self,block_addr):
        project=self._analysis.project
        manager = ailment.Manager(arch=project.arch)
        block = project.factory.block(block_addr)
        ail_block = ailment.IRSBConverter.convert(block.vex, manager)
        simp = project.analyses.AILBlockSimplifier(ail_block,  self.cur_fun.addr)
        csm = project.analyses.AILCallSiteMaker(simp.result_block)
        return  
        
    
    def process_sub_42a978(self,function, state, codeloc, d1,blk=None)    :
        
        d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
        
        #self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr].content
        
        
       
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        ''' 
        # (abs( state.current_codeloc.ins_addr - int(0x441548) ))
        if blk==None :
            blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
            
        print(blk.statements[-1])
        
        if hasattr(blk,"statements") and len(blk.statements) >0 :
            call_statement= blk.statements[-1]
            if type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >2 :
                arg0=call_statement.args[2] 
                if hasattr(arg0,'base') :
                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                    bb=""
                    #if self.dec is not None:
                    #    xx=self.dec.codegen.ailexpr2cnode[(call_statement,False)].c_repr()
                    #    bb=xx.split('"')[1]
                    
                   
                    
                    if  d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                        bb1=self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr]
                        i=0
                        while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                            i+=1
                        bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]

                        if len(bb)==0:
                            arg=blk.statements[-1].args[0]
                            if hasattr(arg,'reg_offset') :
                                for smt in blk.statements:
                                    if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name'] == state.arch.register_names[d1.atom.reg_offset] and type(smt.src) == ailment.expression.Const:
                                        i=0
                                        while str(self.cfg.project.loader.memory.load(smt.src.value, i))[i+1] != '\\':
                                              i+=1
                                        bb=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                                        print("Did I arrived here")
                                        break

                    
                    
                    try:
                        if bb=="":
                            bb=self.get_stringby_use_def(d1,state)
                    except Exception as e:
                        bb=""
                            
                    
                    if 1==0 and bb=="":
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    
                    
                    length=-1
                    try:
                        if len(call_statement.args)==4 and type(call_statement.args[3]) ==ailment.expression.Const :
                            length=call_statement.args[3].value
                        else:
                            d3 = self.get_def_from_parameter(function, parameter_position=3, state=state)
                            if len(call_statement.args)==3 and len(blk.statements)==1:
                                simp_blk=self.get_simp_blk(block_addr=blk.addr)
                            else:
                                simp_blk=blk.statements
                            for stmt in simp_blk.statements:
                                if type(stmt) ==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == d3.offset and type(stmt.src)==ailment.expression.Const :
                                    length=stmt.src.value
                                    break
                    except Exception as e:
                        print(e)
                        print("error in 2658")
                        '''
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                    
                    tags = {ReturnValueTag(
                        function=function.addr,
                        metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length})}
                    
                    '''
                    if bb=="wan_dns2_sec" :
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    '''
                    

                    data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)

                    # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

                    tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                    # state.add_use(atom, tmp_codeloc)
                    try:
                        mv = state.kill_and_add_definition(atom,state.current_codeloc, data, tags=tags)
                    except Exception as e:
                        missing_def = Definition(atom, state.current_codeloc)
                        val =bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                        data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, len(bb) * state.arch.byte_width), missing_def) )
                        mv = state.kill_and_add_definition(atom, state.current_codeloc, data, tags=tags)
                        
                        
                    ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                    #ff = [d for d in ff_defs][0]
                    ff=next( iter(ff_defs) )
                    
                    
                    
                    state.dep_graph.add_node(ff)
                    state.dep_graph.add_edge(d1, ff)
                    print(ff)
                    #state.add_use_by_def(d1, d1.codeloc, None)
                    
                    try:
                        ret_register_name=state.arch.register_names[state.arch.ret_offset]
                        ret_register_name_size=state.arch.registers[ret_register_name]
                        ret_atom = Register(ret_register_name_size[0], ret_register_name_size[1])
                        mv = state.kill_and_add_definition(ret_atom, state.current_codeloc, data, tags=tags)#tags_2)
                        
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        state.dep_graph.add_edge(ff,new_rax)
                        if function.name not in New_input_getters:
                            New_input_getters.append(function.name)
                        
                    except Exception as e:
                        print(e)
                        #raise(e)
                    return True, state

                # to address uVar3 = FUN_0040e898(&local_1a8,"proto",acStack524);
                #pcVar1 = websGetVar(wp,"powerSaveDelay","1") # sometimes it looks like this
                # check rc binary (stop_wan6 function)
                elif hasattr(arg0,'reg_offset') or  d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:   
                    
                    d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
                    b=""
                    if  d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:                        
                        pred=[d for d in state.dep_graph.predecessors(d1)]
                        '''
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        bb=""
                        if len(pred)==1 and type(pred[0].atom)!=MemoryLocation: # to fix situation with getenv in function NK_UiOpenVPNEmailFile
                            pred=[d for d in state.dep_graph.predecessors(pred[0])]
                        for defination in pred :
                                if type(defination.atom)==MemoryLocation  and 'readonly' in  f'{defination}' :
                                    i=0
                                    while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                          i+=1
                                    bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]                                    
                                    break
                        if len(bb)==0 and d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:
                            bb=self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr].content
                            if len(bb)>2 :
                                bb=bb[2:-1]
                        
                        
                        
                        

                        if len(bb)==0:
                            arg=blk.statements[-1].args[0]
                            if hasattr(arg,'reg_offset') :
                                for smt in blk.statements:
                                    if type(smt) == ailment.statement.Assignment and smt.dst.tags['reg_name'] == state.arch.register_names[d1.atom.reg_offset] and type(smt.src) == ailment.expression.Const:
                                        i=0
                                        while str(self.cfg.project.loader.memory.load(smt.src.value, i))[i+1] != '\\':
                                              i+=1
                                        bb=str(self.cfg.project.loader.memory.load(smt.src.value, i-1))[2:-1]
                                        print("Did I arrived here")
                                        break

                    
                    
                        try:
                            if bb=="":
                                bb=self.get_stringby_use_def(d1,state)
                        except Exception as e:
                            bb=""

                        
                        
                        
                        '''
                        if abs(state.current_codeloc.ins_addr - int(0x441548) ) <=8:
                                        import ipdb;
                                        ipdb.set_trace()
                                        pass
                        ''' 
                        
                        
                        if len(bb)>1:
                            #tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                            tags = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':-1})}
                            ret_register_name=state.arch.register_names[state.arch.ret_offset]
                            ret_register_name_size=state.arch.registers[ret_register_name]
                            atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
                            
                            data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                            
                            #mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                            mv = state.kill_and_add_definition(atom, state.current_codeloc, data, tags=tags)
                            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                            new_rax = [d for d in ff_defs][0]
                            d1.tags.update(tags)
                            state.dep_graph.add_edge(d1,new_rax)
                            
                            if function.name not in New_input_getters:
                                New_input_getters.append(function.name) 
                            return True, state

                        
                    for stmt in blk.statements:
                        if type(stmt) ==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == arg0.reg_offset and hasattr(stmt.src,'base') :
                            atom=MemoryLocation(SpOffset(state.arch.bits,stmt.src.offset),stmt.src.size)
                            bb=""
                            if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                                bb1= self.cfg.insn_addr_to_memory_data[d1.codeloc.ins_addr]#.content
                                
                                i=0
                                while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                                    i+=1
                                bb=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                                
                                
                            if bb=="":
                                bb=self.get_stringby_use_def(d1,state)    
                                
                            length=-1
                            try:
                                d3 = self.get_def_from_parameter(function, parameter_position=3, state=state)
                                if len(call_statement.args)==3 and len(blk.statements)==1:
                                    simp_blk=self.get_simp_blk(block_addr=blk.addr)
                                else:
                                    simp_blk=blk.statements


                                for stmt in simp_blk.statements:
                                    if type(stmt) ==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == d3.offset and type(stmt.src)==ailment.expression.Const :
                                        length=stmt.src.value
                            except Exception as e:
                                print("error in 2724")
                               
                            
                            tags = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length})}
                            data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                            tmp_codeloc = state.current_codeloc
                            #mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                            
                            try:
                                mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                            except Exception as e:
                                missing_def = Definition(atom, state.current_codeloc)
                                val =bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                                data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, len(bb) * state.arch.byte_width), missing_def) )
                                mv = state.kill_and_add_definition(atom, state.current_codeloc, data, tags=tags)
                            
                            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                            ff=next( iter(ff_defs) )
                            state.dep_graph.add_node(ff)
                            state.dep_graph.add_edge(d1, ff)
                            
                            
                            
                            tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}

                            ret_register_name=state.arch.register_names[state.arch.ret_offset]
                            ret_register_name_size=state.arch.registers[ret_register_name]
                            atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
                            
                            
                            mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags_2)
                            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                            new_rax = [d for d in ff_defs][0]
                            state.dep_graph.add_edge(ff,new_rax)
                            
                            if function.name not in New_input_getters:
                                New_input_getters.append(function.name) 
                            
                            
                            '''
                            import ipdb;
                            ipdb.set_trace()
                            pass
                            '''
                            
                            return True, state                              
                                
                            
                
                
    
    def xxx_handle_external_function_name(
        self,
        state: "ReachingDefinitionsState",
        ext_func_name: str,
        src_codeloc: Optional["CodeLocation"] = None,
    ) -> Tuple[bool, "ReachingDefinitionsState"]:
        
        function = self._analysis.project.kb.functions.function(name=ext_func_name) 
        
        #blk=self.get_clinic_block(self.clinic,src_codeloc.block_addr)
        blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        d1 = self.get_def_from_parameter(function, parameter_position=0, state=state) 
        function_name=function.name
         #'''
        
        if function_name=='inet_addr':
            import ipdb;
            ipdb.set_trace()
            pass
        
        
        return True, state
       
    
    
    
    def handle_generic(self, state:"ReachingDefinitionsState", src_codeloc: Optional["CodeLocation"] = None) :
        """
        The RDA encountered a function call with multiple possible values, or TOP as a target
        :param state:
        :param src_codeloc:
        :return:
        """
        print("Soory generic")
        return True,state
        #blk=self.get_clinic_block(self.clinic,src_codeloc.block_addr)
        if hasattr(blk.statements[-1].target,'value'):
            function=self.cfg.functions.get_by_addr(addr=blk.statements[-1].target.value)
            try:
                flag,state, *rest = self.handle_local_function(state,function.addr,0,5,self._analysis.visited_blocks,self._analysis.dep_graph,src_codeloc.ins_addr, src_codeloc)
            except Exception as e:
                   return True, state
            return flag, state
        else:
            return True, state
            import ipdb;
            ipdb.set_trace()
            pass
        function_name=function.name
        return False, state
        '''
        if function_name=='inet_addr':
            import ipdb;
            ipdb.set_trace()
            pass
        '''
    
    def XX_handle_general_plt_function(self,function, state, codeloc,blk=None):
        
        d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
        d0=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0,blk=blk)
        
        ret_register_name=state.arch.register_names[state.arch.ret_offset]
        ret_register_name_size=state.arch.registers[ret_register_name]
        atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
        
        tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
        '''
        if function.name=="inet_addr":
            import ipdb;
            ipdb.set_trace()
            pass
        '''
        if d0.atom == atom:  #For ARM architecture
            d0.tags.clear()
            d0.tags.update(tags_2)
            new_rax=d0
        
        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
        try:
            mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
        except Exception as e:
            print(e)
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
            
        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
        new_rax = [d for d in ff_defs][0]
        state.dep_graph.add_edge(d0,new_rax)    
        
        return True, state
    
    
    def recover_calling_convention(self,blk):
            arguments=[]
            recovered_args=[]
            
            
            flag=False
            try:
                ARG_REGS=blk.statements[-1].calling_convention.ARG_REGS 
            except Exception as e :
                flag=True
        
        
            try:
                if flag and "MIPS" in self._analysis.project.arch.name:
                    ARG_REGS=["a0","a1","a2",'a3']
                elif flag and "ARM" in self._analysis.project.arch.name:                    
                    ARG_REGS=["r0","r1","r2",'r3']            
            except Exception as e :
                print(e)
            
            
            
            for arg in ARG_REGS :
                
                parameter=None
                for stmt in blk.statements:
                    # r2<4> = stack_base-4252 or  r1<4> = 0xa1db7<32>                     
                    if type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and  stmt.dst.tags['reg_name']== arg and (  type(stmt.src) == ailment.expression.StackBaseOffset  or type(stmt.src) ==ailment.expression.Const) :
                        parameter=stmt.src
                    
                    if type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and  type(stmt.src)== ailment.expression.Register and  stmt.src.tags['reg_name']== arg:
                        parameter=stmt.src
                        
                    if parameter is None and type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and  stmt.dst.tags['reg_name']== arg:
                        parameter=stmt.dst 
                        
                    #if type(stmt)==ailment.statement.Store :#and hasattr(stmt,"variable") and  hasattr(stmt.variable,"offset"):
                        
                    
                arguments.append(parameter)
            
            if arguments[0] is not None:
                recovered_args.append( arguments[0])  
                if arguments[1] is not None:
                    recovered_args.append( arguments[1])    
                    if arguments[2] is not None:
                        recovered_args.append( arguments[2])    
                        if arguments[3] is not None :
                            recovered_args.append( arguments[3])
            
            for stmt in blk.statements:
                print(stmt)
            print(" recovered args are ", recovered_args   , "block addr -> ", hex(blk.addr) )
            
            return recovered_args
            

    def handle_local_function(self, state, function_address, call_stack, maximum_local_call_depth, visited_blocks,
                              dependency_graph, src_ins_addr=None, codeloc=None):
        function = self._analysis.project.kb.functions.function(function_address)
        if function is None :
            return True, state, visited_blocks, dependency_graph
        
        function_name = function.demangled_name
        print(function_name, function_address,"- is system call ->", function.is_plt,f'src_ins_addr={hex(src_ins_addr)}' ,"  codeloc -> ", hex(codeloc.block_addr), " --> ", hex(codeloc.ins_addr))
        if function_name=='NK_db_write' or function_name=="name_get_value":
            return True, state, visited_blocks, dependency_graph
       
        if state.current_codeloc is None :# or type(state.current_codeloc)==int :
            state.current_codeloc= codeloc
        try:  
            blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
        except Exception as e:
            blk=self.get_clinic_block(self.clinic,codeloc.block_addr)
        
        
        #### This is very dangerious , I have added it recently, you can remvove it in the future if something went wrong    
        if hasattr(blk,"statements") and  len(blk.statements) ==0:#  and ( hasattr(blk.statements[-1],"args") and len(blk.statements[-1].args)==0 ) :
             blk=get_clinic_block(self._analysis.project,self.clinic, state.current_codeloc.block_addr)
        
        
        # rebuild Calling convention
        if hasattr(blk,"statements") and len(blk.statements) >0  and  hasattr(blk.statements[-1],"args") and len(blk.statements[-1].args) ==0:
            recovered_args= self.recover_calling_convention(blk)
            if len(recovered_args)>0:
                blk.statements[-1].args=recovered_args
                
        '''
        if hasattr(blk,"statements") and len(blk.statements) >0  and  hasattr(blk.statements[-1],"args") and len(blk.statements[-1].args) ==0:
            arguments=[]
            for arg in blk.statements[-1].calling_convention.ARG_REGS :
                
                parameter=None
                for stmt in blk.statements:
                    # r2<4> = stack_base-4252 or  r1<4> = 0xa1db7<32> 
                    
                    if type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and  stmt.dst.tags['reg_name']== arg and (  type(stmt.src) == ailment.expression.StackBaseOffset  or type(stmt.src) ==ailment.expression.Const) :
                        parameter=stmt.src
                    
                    if type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and  type(stmt.src)== ailment.expression.Register and  stmt.src.tags['reg_name']== arg:
                        parameter=stmt.src
                        
                    if parameter is None and type(stmt) == ailment.statement.Assignment and type(stmt.dst)== ailment.expression.Register and    stmt.dst.tags['reg_name']== arg:
                        parameter=stmt.dst 
                    
                arguments.append(parameter)
            
            if arguments[0] is not None
                blk.statements[-1].args.append(parameter)  
            if arguments[1] is not None
                blk.statements[-1].args.append(parameter)    
            
            if arguments[0] is not None and arguments[1] is not None:
                blk.statements[-1].args.append(parameter)    
            if arguments[0] is not None and arguments[1] is not None and arguments[2] is not None :
                blk.statements[-1].args.append(parameter)
            
            for stmt in blk.statements:
                print(stmt)
            print(" recovered args are ", blk.statements[-1].args)
        '''      
                    
                
            
        
        #print("inside handle local")
        #print(blk)
        #print("----------")
        #print('handle_{}'.format(function_name))
        func = getattr(MyHandler, 'handle_{}'.format(function_name), None)
        if func is not None :
            try:
                flag,state=func(self, state, codeloc)
            except Exception as e:
                print(e)
            return True,state, visited_blocks, dependency_graph
            
        num_arguments= len(function.arguments) 
        if len(function.arguments)==0:
            if blk is not None and hasattr(blk,"statements") and len(blk.statements) >0  and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None:
                num_arguments=len(blk.statements[-1].args)
        collect_definatins=[]
        for ii in  range(num_arguments):
            try:
                d0 = self.get_def_from_parameter(function, parameter_position=ii, state=state,blk=blk)
                collect_definatins.append(d0) # I added it to check if d0 is tainted later for interprocedural thing
                if ii==0:
                    first_defination=d0
                d0 = self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=ii,blk=blk)
                tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                
                if type(d0.atom)==MemoryLocation:
                    d0.tags.update(tags)
                    collect_definatins.append(d0)
                else:
                    
                    if d0 in state.dep_graph.nodes():
                        pred=[d for d in state.dep_graph.predecessors(d0)]
                        for df in pred:
                            if type(df.atom)==MemoryLocation:
                                df.tags.update(tags)
                                collect_definatins.append(df)
                                                                        
                                
            except Exception as e:
                continue
                #print(e)
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                '''
        
        
        #if state.current_codeloc is None or type(state.current_codeloc)==int :
        #    state.current_codeloc= codeloc
        # this is new to try to find sanitization function'
        # save_blk_and_definitions_to_json(blk, collect_definatins, f"{function_address}.json")
        # save_json({"blk":blk,"collect_definatins":collect_definatins},f"{function_address}.json")
        if function.has_return and len(collect_definatins) >0:
            ret_register_name=state.arch.register_names[state.arch.ret_offset]
            ret_register_name_size=state.arch.registers[ret_register_name]
            atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)
            try:
                tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'parameter_pass':1})}
            except Exception as e:
                print(e)
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                '''
            if first_defination is not None:                            
                if  first_defination.atom == atom:  #For ARM architecture
                    #d0.tags.clear()
                    first_defination.tags.update(tags_2)
                    new_rax=first_defination

                data: MultiValues = state.register_definitions.load(first_defination.atom.reg_offset, size=first_defination.atom.size)
                try:
                    mv = state.kill_and_add_definition(atom, first_defination.codeloc, data, tags=tags_2)
                except Exception as e:
                    print(e)
                    '''
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    '''

                ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                new_rax = [d for d in ff_defs][0]
                for d0 in collect_definatins:
                    state.dep_graph.add_edge(d0,new_rax)  


    
                    
            
       
            
        
        
        if  function.is_plt and num_arguments==1 and function.has_return:
            flag,state=self.XX_handle_general_plt_function(function, state, codeloc,blk=blk)
            return True,state, visited_blocks, dependency_graph
        
        # to address situation such as fopen()
        if function.is_plt : 
            return True,state, visited_blocks, dependency_graph
        
        
        '''
        to address libc fnctions wrappers e.g ororola C1 prog.cgi fnction=sub_42048c
        '''
        callees=[ item.name  for item in function.functions_called() if item.name]
        if len(callees)==1:
            func = getattr(MyHandler, 'handle_{}'.format(callees[0]), None)
            if func is not None :
                flag,state=func(self, state, codeloc)
                return True,state, visited_blocks, dependency_graph
            else:
                tmp_fun=self._analysis.project.kb.functions.function(name=callees[0])
                if tmp_fun.is_plt : 
                    return True,state, visited_blocks, dependency_graph
            
        
        
        #if function_name =="sub_55a73c" or function_name=="ambitSetLogFilter":
        #     return True,state, visited_blocks, dependency_graph
        
        '''
        if function_name== "sub_184c0":# and  global_counter[0]<2 :
            import ipdb;
            ipdb.set_trace()
            pass
        '''
       
        
       
        
        # to address similar incidence sub_184d4(v5, "iserver_passcode", &v2);
        try:
            if  blk is not None and hasattr(blk,"statements") and len(blk.statements) >0 and type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) >2 :
                arg0=blk.statements[-1].args[2] 
                if hasattr(arg0,'base') :
                    d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
                    d2 = self.get_def_from_parameter(function, parameter_position=2, state=state)
                    #blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
                    if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                        self.process_sub_42a978(function, state, codeloc, d1,blk)
                        return True,state, visited_blocks, dependency_graph
                    elif d2.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data:
                        #d2 = self.get_def_from_parameter(function, parameter_position=2, state=state)
                        #if d2.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                        self.process_sub_42a978(function, state, codeloc, d2,blk)
                        return True,state, visited_blocks, dependency_graph
                    else:
                        project=self._analysis.project
                        manager = ailment.Manager(arch=project.arch)
                        block = project.factory.block(d0.codeloc.block_addr)
                        ail_block = ailment.IRSBConverter.convert(block.vex, manager)
                        simp = project.analyses.AILBlockSimplifier(ail_block,  self.cur_fun.addr)
                        csm = project.analyses.AILCallSiteMaker(simp.result_block)

                        if csm.result_block:
                            ail_block = csm.result_block
                            
                        bb=""
                        for stmt in simp.result_block.statements:
                            if type(stmt)==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == arg0.reg_offset and hasattr(stmt.src,'base') :
                                str_atom=MemoryLocation(SpOffset(state.arch.bits,stmt.src.offset),stmt.src.size)
                                mem_def=[d for d in state.get_definitions(str_atom)][0]
                                curr_tag = (mem_def.tags.copy()).pop()
                                if 'token' in curr_tag.metadata: 
                                    bb=curr_tag.metadata['token']
                                    
                                    
                                    atom=MemoryLocation(SpOffset(state.arch.bits,arg0.offset),arg0.size)
                                    
                                   

                                    tags = {ReturnValueTag(
                                        function=function.addr,
                                        metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb})}

                                    data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)

                                    # result = MultiValues(offset_to_values={0: {self.state.top(size * self.arch.byte_width)}})

                                    tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                                    # state.add_use(atom, tmp_codeloc)
                                    #mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                                    
                                    try:
                                        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                                    except Exception as e:
                                        missing_def = Definition(atom, state.current_codeloc)
                                        val =bb# self.project.loader.memory.unpack_word(addr_v, size=size)
                                        data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(val, len(bb) * state.arch.byte_width), missing_def) )
                                        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags)
                                    
                                    
                                    ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                                    #ff = [d for d in ff_defs][0]
                                    ff=next( iter(ff_defs) )



                                    state.dep_graph.add_node(ff)
                                    state.dep_graph.add_edge(d1, ff)
                                    
                                    if function.name not in New_input_getters:
                                        New_input_getters.append(function.name)
                                    
                                    
                                    
                                    return True,state, visited_blocks, dependency_graph
                            
                        
                        
                elif hasattr(arg0,'reg_offset') :   
                    d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
                    if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                        for stmt in blk.statements:
                            if type(stmt)==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == arg0.reg_offset and hasattr(stmt.src,'base') :
                                self.process_sub_42a978(function, state, codeloc, d1,blk)
                                return True,state, visited_blocks, dependency_graph
                            
                # to handle FUN_0002ba8c(param_1,"deviceName",&DAT_000f1f54); where v2 = sub_2ba8c(a0, &g_f2208, &g_f1f54); --> resulted by angr decompiler version 9.2.44 
                arg0=blk.statements[-1].args[1] 
                call_statement=blk.statements[-1]
                d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
                #if function_name=="sub_2ba8c" :
                #    global_counter[0]+=1
                    
                
                if function.has_return and  hasattr(arg0,'reg_offset'):
                    for stmt in blk.statements:
                           if type(stmt)==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == arg0.reg_offset and hasattr(stmt.src,'value'):
                                address=stmt.src.value
                                i=1
                                while str(self.cfg.project.loader.memory.load(address, i))[i+1] != '\\':
                                    i+=1
                                bb=str(self.cfg.project.loader.memory.load(address, i-1))[2:-1]
                                if len(bb) <4:
                                    continue
                                #print("our new adjustment")
                                #print(bb)
                                
                                
                                length=-1
                                try:
                                    d3 = self.get_def_from_parameter(function, parameter_position=3, state=state)
                                    for stmt in blk.statements:
                                        if type(stmt) ==ailment.statement.Assignment and hasattr(stmt.dst,'reg_offset') and stmt.dst.reg_offset == d3.offset and type(stmt.src)==ailment.expression.Const :
                                            length=stmt.src.value
                                except Exception as e:
                                    print("error in 3100")
                                
                                
                                tags = {ReturnValueTag(function=function.addr,  metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb,'length':length})}

                                data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                                tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                                mv = state.kill_and_add_definition(d1.atom, d1.codeloc, data, tags=tags)
                                ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                                ff=next( iter(ff_defs) )
                                    
                                    
                                ret_register_name=state.arch.register_names[state.arch.ret_offset]
                                ret_register_name_size=state.arch.registers[ret_register_name]
                                ret_atom = Register(ret_register_name_size[0], ret_register_name_size[1])
                                mv = state.kill_and_add_definition(ret_atom, d1.codeloc, data, tags=tags)
                                ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                                new_rax = [d for d in ff_defs][0]
                                state.dep_graph.add_edge(ff,new_rax)
                                
                                if function.name not in New_input_getters:
                                    New_input_getters.append(function.name)
                                
                                '''
                                import ipdb;
                                ipdb.set_trace()
                                pass
                                '''
                                
                                return True,state, visited_blocks, dependency_graph

                                
                    
                    
                    '''
                    if global_counter[0]==4:
                        for n in self.dec.clinic.graph.nodes:
                            if n.addr==blk.addr:
                                node=n
                                print(n)   
                                import ipdb;
                                ipdb.set_trace()
                                pass     
                        
                    '''
                    node=None
                    for n in self.dec.clinic.graph.nodes:
                        if n.addr==blk.addr:
                            node=n
                            #print(n) 
                            break
                            '''
                            import ipdb;
                            ipdb.set_trace()
                            pass
                            '''
                        
                    #if node is not None and asattr(node,"statements") and len(node.statements) >0 and and  hasattr(node.statements[-1],"data")  hasattr(node.statements[-1].data,"args") and node.statements[-1].data.args is not None and len(node.statements[-1].data.args) >2  and hasattr(=node.statements[-1].data.args[1],"value"):
                    if  node is not None and self.dec is not None and (node,False) in self.dec.codegen.ailexpr2cnode:    
                        address=node.statements[-1].data.args[1].value
                        i=1
                        while str(self.cfg.project.loader.memory.load(address, i))[i+1] != '\\':
                            i+=1
                        bb=str(self.cfg.project.loader.memory.load(address, i-1))[2:-1]
                        if  not len(bb) <4:
                            
                            #print("our new  second adjustment")
                            #print(bb)
                            tags = {ReturnValueTag(function=function.addr,  metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'token':bb})}

                            data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                            tmp_codeloc = state.current_codeloc  # codeloc  # CodeLocation(ins_addr=src_ins_addr,block_addr=caller_function.addr,stmt_idx=7)
                            mv = state.kill_and_add_definition(d1.atom, d1.codeloc, data, tags=tags)
                            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                            ff=next( iter(ff_defs) )
                                    
                                    
                            ret_register_name=state.arch.register_names[state.arch.ret_offset]
                            ret_register_name_size=state.arch.registers[ret_register_name]
                            ret_atom = Register(ret_register_name_size[0], ret_register_name_size[1])
                            mv = state.kill_and_add_definition(ret_atom, d1.codeloc, data, tags=tags)
                            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                            new_rax = [d for d in ff_defs][0]
                            state.dep_graph.add_edge(ff,new_rax)
                            if function.name not in New_input_getters:
                                New_input_getters.append(function.name)
                            return True,state, visited_blocks, dependency_graph
                            
                            
                    #'''
        
        
        
        
       
    
        
        except Exception as e:
            dddddddddd=0
            #raise e
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            '''
            #return True,state, visited_blocks, dependency_graph
        
       
        #''' this is similar to the previous code, if the previous work, no need for this
        if function_name== "sub_42a978" or function_name=="sub_184d4"  :
            d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)
            #blk=self.get_clinic_block(self.clinic,state.current_codeloc.block_addr)
            if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                self.process_sub_42a978(function, state, codeloc, d1)
            else:
                d2 = self.get_def_from_parameter(function, parameter_position=2, state=state)
                if d2.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data :
                    self.process_sub_42a978(function, state, codeloc, d2)
            #import ipdb;
            #ipdb.set_trace()
            #pass
            return True,state, visited_blocks, dependency_graph
            
        #'''
        
        
        
         
        
        
        
        ###return True, state, visited_blocks, dependency_graph
        # to address uVar1 = FUN_0002fa0c("productid");
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        # sometimes angr does not recognizes correctly the number of passed parameters to the function
        # from the dissaseemply we can see that the function recieve two parameters, but angr recognizes only one
        if  (len(function.arguments)==2 or len(function.arguments)==1 ) and function.has_return:
            cc = function.calling_convention

            parameter_position = 0
            parameter_atom = Atom.from_argument(
                SimRegArg(cc.ARG_REGS[parameter_position], state.arch.bytes),
                self._analysis.project.arch.registers
            )
            '''
            if function.name=="sub_2fa0c":
                import ipdb;
                ipdb.set_trace()
                pass
            '''    

        
            def0 = state.get_definitions(parameter_atom)
            d0 = [d for d in def0][0]
            
           
            callees=[ item.name  for item in function.functions_called() if item.name in SOURCES]
            if len(callees)!=0 :
                temp_function = self._analysis.project.kb.functions.function(name=callees[0])#"nvram_get")
                #tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{"nvram_get"} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                tags_2 = {ReturnValueTag(function=temp_function.addr, metadata={'tagged_by': f'{temp_function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}

                ret_register_name=state.arch.register_names[state.arch.ret_offset]
                ret_register_name_size=state.arch.registers[ret_register_name]
                atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)

                if d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data  :

                    if d0.atom == atom:
                        d0.tags.update(tags_2)
                        new_rax=d0
                    else:
                        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
                        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
                        mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        state.dep_graph.add_edge(d0,new_rax)
                        
                    if function.name not in New_input_getters:
                        New_input_getters.append(function.name)
                        
                    return True,state, visited_blocks, dependency_graph


                # uVar1 = FUN_00425918(param_2,"ping_times");
                elif not d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data    :
                    d1 = self.get_def_from_parameter(function, parameter_position=1, state=state)

                    if d1.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data  :
                        data: MultiValues = state.register_definitions.load(d1.atom.reg_offset, size=d1.atom.size)
                        mv = state.kill_and_add_definition(atom, d1.codeloc, data, tags=tags_2)
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        state.dep_graph.add_edge(d1,new_rax)
                        if function.name not in New_input_getters:
                            New_input_getters.append(function.name)
                        return True,state, visited_blocks, dependency_graph
            
            elif d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data  :
                tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                ret_register_name=state.arch.register_names[state.arch.ret_offset]
                ret_register_name_size=state.arch.registers[ret_register_name]
                atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)

                if d0.codeloc.ins_addr in self.cfg.insn_addr_to_memory_data  :

                    if d0.atom == atom:
                        d0.tags.update(tags_2)
                        new_rax=d0
                    else:
                        data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
                        # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
                        mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        state.dep_graph.add_edge(d0,new_rax)
                    
                    if function.name not in New_input_getters:
                        New_input_getters.append(function.name)
                    
                    return True,state, visited_blocks, dependency_graph


                '''
                import ipdb;
                ipdb.set_trace()
                pass
                
                print("new_rax")
                try:
                    print(new_rax)
                except Exception as e:
                    print(e)
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    
                write_dot(state.dep_graph.transitive_closure(new_rax), "zz.dot")
                os.system("dot -Tsvg -o ss.svg zz.dot")
                ''' 
                #return True,state, visited_blocks, dependency_graph

        
        
        
        if  hasattr(blk,"statements"):
            call_statement=blk.statements[-1]
        if function.has_return and blk is not None and hasattr(blk,"statements") and len(blk.statements) >0 and type(blk.statements[-1]) == ailment.statement.Call and  hasattr(blk.statements[-1],"args") and blk.statements[-1].args is not None and len(blk.statements[-1].args) ==2 :
            if len(call_statement.args)==2:
                bb=""
                d0 = self.get_def_from_parameter(function, parameter_position=0, state=state)
                if type(d0.atom)==MemoryLocation   and 'External' in f'{d0.codeloc}' :
                    pred=[d for d in state.dep_graph.predecessors(d0)]
                    if len(pred)==1 and type(pred[0].atom)==MemoryLocation:
                        for defination in pred :
                            if type(defination.atom)==MemoryLocation:
                                i=0
                                while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                      i+=1
                                bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]
                                break
                elif type(d0.atom)!=Register:
                    pred=[d for d in state.dep_graph.predecessors(d0)]
                    if len(pred)==1 and type(pred[0].atom)==MemoryLocation and  'External' in f'{pred[0].codeloc}':
                        pred=[d for d in state.dep_graph.predecessors(pred[0])]
                        
                        if len(pred)==1 and type(pred[0].atom)==MemoryLocation:
                            for defination in pred :
                                if type(defination.atom)==MemoryLocation:
                                    i=0
                                    while str(self.cfg.project.loader.memory.load(defination.atom.addr, i+1))[i+1] != '\\':
                                          i+=1
                                    bb=str(self.cfg.project.loader.memory.load(defination.atom.addr, i-1))[2:-1]
                                    break
                
                
                if len(bb)>4:
                    tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
                    ret_register_name=state.arch.register_names[state.arch.ret_offset]
                    ret_register_name_size=state.arch.registers[ret_register_name]
                    atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)

                    if 1==1  :

                        if d0.atom == atom:
                            d0.tags.update(tags_2)
                            new_rax=d0
                        else:
                            if type(d0.atom)==Register:
                                data: MultiValues = state.register_definitions.load(d0.atom.reg_offset, size=d0.atom.size)
                            elif type(d0.atom)==MemoryLocation:
                                data: MultiValues  = MultiValues(state.annotate_with_def(claripy.BVV(bb, len(bb) * state.arch.byte_width), missing_def) )
                            # mv = state.kill_and_add_definition(rdi_pred.atom, rdi_pred.codeloc, data, tags=tags_2)
                            mv = state.kill_and_add_definition(atom, d0.codeloc, data, tags=tags_2)
                            ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                            new_rax = [d for d in ff_defs][0]
                            state.dep_graph.add_edge(d0,new_rax)

                        if function.name not in New_input_getters:
                            New_input_getters.append(function.name)
                       
                    
                    return True,state, visited_blocks, dependere_graph
        
       
        
        # to add label
        
        #if  num_arguments==1 and function.has_return:
        #    flag,state=self.XX_handle_general_plt_function(function, state, codeloc,blk=blk)
        
        
        '''
        if function_name=="sub_17190":#2ba8c":#"sub_40e898":
            
            if hasattr(blk,"statements") and len(blk.statements) >0 :
            for smt in blk.statements :
                    if type(smt) == ailment.statement.Assignment and type(smt.src) == ailment.expression.StackBaseOffset and  smt.dst.tags['reg_name']== state.arch.register_names[d0.atom.reg_offset]:
            
            return True,state
            import ipdb;
            ipdb.set_trace()
            pass
        ''' 
        
        
        
        
        '''
        if 1==0 and function.name=="sub_2c4b0":#'sub_4da1c':
            import ipdb;
            ipdb.set_trace()
            pass
        '''
        
        '''
        if hasattr(blk,"statements") and len(blk.statements) >0  and  hasattr(blk.statements[-1],"args") and len(blk.statements[-1].args) ==0:
            import ipdb;
            ipdb.set_trace()
            pass
        ''' 
        
        if 1==0 and  function.name=="sub_52db4":  #1==0 and  src_ins_addr ==0x127c8:
            import ipdb;
            ipdb.set_trace()
            pass
            
        
        ## inter-procedural
        ##return True,state, visited_blocks, dependency_graph
        if len(function.arguments)==0 and hasattr(blk,"statements") and len(blk.statements) >0 and  hasattr(blk.statements[-1],"args") and len(blk.statements[-1].args)==0:
            return True,state, visited_blocks, dependency_graph
        
        
        # this procedure to avoid visiting functions which are not tainted by any of its parameters
        to_continue_flag=False
        if len(collect_definatins)>0:
        

            # rd_ddg_graph = rd.dep_graph
            # Instantiate the object that will walk back the dep_graph.
            def_explorer = DefinitionExplorer(self._analysis.project, state.dep_graph, self.get_cfg())
            def_explorer.set_current_state(state)
            def_explorer.set_current_codeloc(codeloc)
            def_explorer.set_RDA_handler(self)
            def_explorer.set_current_fucntion(self.cur_fun)
            
            
            for d0 in collect_definatins:
                if to_continue_flag:
                    break
            
                ff_list=[d0]
                ff=self.get_memory_defination(d0,function,state,codeloc,defination_only=True,defination_location=0,blk=blk)
                ff_list=[d0,ff]
                tmp_ff=self.get_memoryDef_by_use_def(d0,state)
                if tmp_ff is not None :
                    ff=[d for d in state.get_definitions(tmp_ff.atom)]
                    if len(ff)!=0:
                        ff_list.append(ff[0])

                for item in ff_list:
                    reg_seen_defs,Paths,visited_functions=backtrack_definations(def_explorer, reg_defs=[item], result_file=self.get_result_file(), memcpy_func_pred=self.get_current_fucntion(), FUNCS=[], sink=function.name,  memcpy_addr=state.current_codeloc.ins_addr, check_is_tainted_def=True)#function.addr)

                    for overall_def, path,visited_function in zip(reg_seen_defs,Paths,visited_functions) :
                        if overall_def[0] == "get2set" or (overall_def[0] == "retval" and overall_def[1] != None ) :
                            to_continue_flag=True
                            break

                    if to_continue_flag:
                        break
        
        
        
        
        
        
        if not  to_continue_flag:
            return True,state, visited_blocks, dependency_graph
        
        
        '''
        if 1==0 function.name=="sub_77838":
            import ipdb;
            ipdb.set_trace()
            pass
        '''
        
        if not function.is_plt:  
            #print("hahahahaah 111111111111111")
            #'''
            if self.cur_fun.name==function.name :
                #print("hahahahah 00000")
                return True, state, visited_blocks, dependency_graph
            #'''
            try:
                shortest_path = nx.shortest_path(self.call_graph, self.start_function.addr, function.addr)
            except Exception as e :
                shortest_path=[]
            if len(shortest_path) >3 :
                #print("hahahaahah 2222")
                return True,state, visited_blocks, dependency_graph
            
            if len(STACK) ==0 :
                STACK.append((self.cur_fun, self.dec, self.clinic,state))
                
            elif  (self.cur_fun, self.dec, self.clinic,state) in STACK :
               # print("hahahaha 333")
                return True, state, visited_blocks, dependency_graph
            else:
                STACK.append((self.cur_fun, self.dec, self.clinic,state))
            
            
            
            self.cur_fun=function
            try:
                self._analysis.project.analyses.VariableRecoveryFast(function )
                
                memcpy_addr = function.addr  
                if 1==1 :#and :memcpy_addr not in Analyzed_Before:
                    #print("hahahahahaahahah")
                    # Get CFG node for memcpy
                    memcpy_node = self.cfg.model.get_any_node(memcpy_addr)
                    # Get all the XRefs (predecessor of the memcpy nodes)
                    memcpy_node_preds = memcpy_node.predecessors
                    # Grab all functions that have an xrefs to the basic function
                    memcpy_funcs_preds = list(set([x.function_address for x in memcpy_node_preds]))
                    dec = self._analysis.project.analyses.Decompiler(function, cfg=self.cfg)
                    ##if len(memcpy_funcs_preds)>0:        
                    ##    Analyzed_Before[memcpy_addr]=dec
                ##else:
                ##    dec= Analyzed_Before[memcpy_addr]
                
                
                
                
                self.dec = dec #self._analysis.project.analyses.Decompiler(function, cfg=self.cfg)
                self.clinic=self.dec.clinic
            except Exception as e :
                print("error at 3528 ",e)
                print(function.name)
                #raise e
                self.dec=None
                self.clinic=None
            

            try :
                child_function_rda = self._analysis.project.analyses.ReachingDefinitions(
                    function_handler=self,  # MyHandler(),
                    observe_all=True,
                    subject=function,
                    cc=function.calling_convention,
                    init_state=state,
                    kb=self._analysis.project.kb, dep_graph=dependency_graph)
                
                
                
                state.analysis.observed_results.update(child_function_rda.observed_results)
            except Exception as e :
                print("error at 3491 ", e)
                #raise e
                self.cur_fun, self.dec, self.clinic,_= STACK.pop()
                return True, state, visited_blocks, dependency_graph    
                
                
                # this is new to try to find sanitization function
            if function.has_return and len(collect_definatins) >0:
                    ret_register_name=state.arch.register_names[state.arch.ret_offset]
                    ret_register_name_size=state.arch.registers[ret_register_name]
                    atom = Register(ret_register_name_size[0], ret_register_name_size[1])#(16, 4)

                    tags_2 = {ReturnValueTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr,'parameter_pass':1})}

                    if first_defination is not None:                            
                        if  first_defination.atom == atom:  #For ARM architecture
                            #d0.tags.clear()
                            first_defination.tags.update(tags_2)
                            new_rax=first_defination

                        data: MultiValues = state.register_definitions.load(first_defination.atom.reg_offset, size=first_defination.atom.size)
                        try:
                            mv = state.kill_and_add_definition(atom, first_defination.codeloc, data, tags=tags_2)
                        except Exception as e:
                            print(e)
                            '''
                            import ipdb;
                            ipdb.set_trace()
                            pass
                            '''

                        ff_defs = state.live_definitions.extract_defs_from_mv(mv=mv)
                        new_rax = [d for d in ff_defs][0]
                        for d0 in collect_definatins:
                            state.dep_graph.add_edge(d0,new_rax) 
                            
            if function.name=='sub_cd088' and 1==0:
                    write_dot(state.dep_graph.transitive_closure(new_rax), "dd.dot")
                    os.system("dot -Tsvg -o dd.svg dd.dot")

                            
                
                
                
                
            
        

        if not function.is_plt:
            
            self.cur_fun, self.dec, self.clinic,_= STACK.pop()
            
            '''
            exit_site_addresses = [b.addr for b in
                                   function.ret_sites + function.jumpout_sites]  # if   ('node', b, OP_AFTER) in child_function_rda.observed_results]
            if exit_site_addresses == [] and self._ret_sites[function.addr] != []:
                exit_site_addresses = self._ret_sites[function.addr]
            if len(exit_site_addresses) > 0:
                state.live_definitions = self._state_from(child_function_rda, exit_site_addresses)
                state.analysis.observed_results.update(child_function_rda.observed_results)

            '''    
            

        return True, state, visited_blocks, dependency_graph  # .update(child_function_rda.dep_graph)
    


# Utility class to walk back the definitions graph.
class DefinitionExplorer():
    def __init__(self, project, rd_ddg_graph, cfg):
        self.project = project
        self.rd_ddg_graph = rd_ddg_graph
        self.cfg = cfg
        
    
    def set_RDA_handler(self, RDA_handler):
        self.RDA_handler = RDA_handler
    
    def set_current_fucntion(self, cur_fun):
        self.cur_fun = cur_fun

    def get_current_fucntion(self):
        return self.cur_fun
        
    def set_d0(self,d0):
        self.d0=d0
    def set_d0_token(self,d0_token):
        self.d0_token=d0_token
    def set_d1(self,d1):
        self.d1=d1
        
    def set_transitive_funtion_name(self,function_name):
        self.transitive_funtion_name=function_name
        
        
    def set_current_state(self,state):
        self.current_state =state
        
    def get_current_state(self):
        return self.current_state
    
    
    def set_current_codeloc(self,codeloc):
        self.current_codeloc=codeloc
        
    def get_current_codeloc(self):
        return self.current_codeloc

    def old_resolve_use_def(self, reg_def):
        # Now we need to analyze the definition for this atom
        reg_seen_defs = set()
        defs_to_check = set()
        defs_to_check.add(reg_def)

        # Cache of all seen nodes (Tie the knot)
        seen_defs = set()

        while len(defs_to_check) != 0:
            current_def = defs_to_check.pop()
            seen_defs.add(current_def)
            # Check if the current Definition has a tag
            def_value = self.check_definition_tag(current_def, reg_def)

            # If def_value is not None we hit a "retval" and we collect it,
            # in the other case we need to check if it is Undefined, if yes gotta walk back.
            if def_value:
                # def_value.append(reg_def.codeloc.ins_addr) #[4] to save the insrtuction address that calls the sink function
                reg_seen_defs.add(def_value)
            else:

                # If we have undefined pointers (a.k.a. Top value) we need to process the predecessors.
                if current_def in self.rd_ddg_graph.graph.nodes():
                    for pred in self.rd_ddg_graph.graph.predecessors(current_def):
                        if pred not in seen_defs:
                            defs_to_check.add(pred)

        return reg_seen_defs
    
    def resolve_use_def(self, reg_def):
        # Now we need to analyze the definition for this atom
        reg_seen_defs = set()
        defs_to_check = [(reg_def, [],[])]  # Use a list as a stack, storing (node, path_so_far)

        # Cache of all seen nodes (Tie the knot)
        seen_defs = set()

        paths = []  # To store all paths leading to nodes with the desired tag
        visited_functions=[]

        while len(defs_to_check) != 0:# defs_to_check:
            current_def, current_path,current_fun = defs_to_check.pop()
            seen_defs.add(current_def)
            current_path = current_path + [current_def]#.codeloc.block_addr]#[current_def]
            
            #tags = {LocalVariableTag(function=function.addr, metadata={'tagged_by': f'{function.name} simulation Effect','block_addr':state.current_codeloc.block_addr})}
            extrated_tags=current_def.tags.copy()
            visited_fun=[]
            if len(extrated_tags)>0:
                while True:
                    curr_tag = extrated_tags.pop()
                    #if type(curr_tag) == LocalVariableTag:
                    #    break
                    if (type(curr_tag) == LocalVariableTag or type(curr_tag) == ReturnValueTag) and hasattr(curr_tag, "function") and 'block_addr' in curr_tag.metadata:
                        length=-1
                        if 'length' in curr_tag.metadata:
                            length= curr_tag.metadata['length']
                        visited_fun.append((curr_tag.metadata['tagged_by'].split()[0],curr_tag.metadata['block_addr'],length)) # sometimes the same defination visit several functions
                    if len(extrated_tags)==0:
                            break
            
                
            current_fun = current_fun + visited_fun
            
            # Check if the current Definition has a tag
            def_value = self.check_definition_tag(current_def, reg_def)

            # If def_value is not None we hit a "retval" and we collect it,
            if def_value:
                reg_seen_defs.add(def_value)
                paths.append(current_path)
                visited_functions.append(current_fun)
            else:
                # If we have undefined pointers (a.k.a. Top value) we need to process the predecessors.
                if current_def in self.rd_ddg_graph.graph.nodes():
                    predecessors = self.rd_ddg_graph.graph.predecessors(current_def)
                    print(self.rd_ddg_graph.graph.predecessors(current_def))
                    for pred in self.rd_ddg_graph.graph.predecessors(current_def):
                        
                        if pred not in seen_defs:
                            defs_to_check.append((pred, current_path,current_fun))
        # with open(f"{current_fun[-1][0]}.json", "a+") as f:
        #     json.dump(current_fun, f,indent=4)
            
        return reg_seen_defs, paths,visited_functions  # Return paths in addition to reg_seen_defs

    
    def get_strings(self,d0):
        b0 = "not_static_string"
        pcd0 = [d for d in self.rd_ddg_graph.predecessors(d0)]
        memory_def_flag = False
        for df in pcd0:
            if type(df.atom) == MemoryLocation and df.atom.addr in self.cfg.memory_data:
                memory_def_flag = True
        if not memory_def_flag:
            extended_defs = []
            for df in pcd0:
                extended_defs.extend([d for d in self.rd_ddg_graph.predecessors(df)])
            pcd0 = extended_defs

        string_list = []
        for df in pcd0:
            if type(df.atom) == MemoryLocation and df.atom.addr in self.cfg.memory_data and self.cfg.memory_data[
                df.atom.addr].content is not None:
                bb0 = self.cfg.memory_data[df.atom.addr]
                if bb0.content is not None:
                    # b0=str(bb0.content)[2:-1]
                    i = 0
                    while str(self.cfg.project.loader.memory.load(bb0.addr, bb0.size + i))[bb0.size + i + 1] != '\\':
                        i += 1
                    b0 = str(self.cfg.project.loader.memory.load(bb0.addr, bb0.size + i - 1))[2:-1]
                    string_list.append(b0)
        if len(string_list) > 1:
            b0 = "#".join(string_list)
            
        return b0
                            

    # Checking the tag over a definition.
    def check_definition_tag(self, definition, reg_def):
        
        
        
        
        
        # to consider golobal variable as a tainted sources
        '''
        if   type(definition.atom) == MemoryLocation and hasattr(definition.atom,"size") and definition.atom.size is not None and definition.atom.size>100  and len(definition.tags)==0 and 'External' in f'{definition}' :
                df=[d for d in self.rd_ddg_graph.predecessors(definition)]
                if len(df)==0:
                    try:
                        extrated_tags=definition.tags.copy()
                        if len(extrated_tags)==0:       
                            print("\n\n inside empty global \n",definition )
                            #import ipdb;
                            #ipdb.set_trace()
                            #pass
                            #      ("retval", curr_tag.function, func.name, definition.codeloc.ins_addr,  self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                            return ("retval", self.cur_fun.addr, "Global_"+hex(definition.atom.addr)[2:],self.current_state.current_codeloc.ins_addr, self.current_state.current_codeloc.ins_addr, "Global_variable",'empty_global')
                    except Exception as e:
                        print("error at 5692")
                        
        
        # t0 address situations where a function that no other functions call it ( it is like a handler)
        if  type(definition.atom) == Register  and 'External' in f'{definition}'   :
                df=[d for d in self.rd_ddg_graph.predecessors(definition)]
                if len(df)==0:
                    try:
                        extrated_tags=definition.tags.copy()
                        if len(extrated_tags)>0:
                            curr_tag = extrated_tags.pop()
                            if hasattr(curr_tag, "function") and curr_tag.function is not None :
                                    func = self.cfg.functions.get_by_addr(curr_tag.function)
                                    memcpy_node=self.cfg.model.get_any_node(func.addr)
                                    memcpy_node_preds = memcpy_node.predecessors
                                    preds=set([x.function_address for x in memcpy_node_preds])
                                    if len(preds)==0:
                                        #return ("retval", curr_tag.function, func.name, definition.codeloc.ins_addr,  self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                                        return ("retval", curr_tag.function, func.name,self.current_state.current_codeloc.ins_addr, self.current_state.current_codeloc.ins_addr, "No_callable_function",'empty_function_parameter')
                            elif  hasattr(definition.codeloc,"call_string") and definition.codeloc.call_string[0]== self.cur_fun.addr:
                                    memcpy_node=self.cfg.model.get_any_node(self.cur_fun.addr)
                                    memcpy_node_preds = memcpy_node.predecessors
                                    preds=set([x.function_address for x in memcpy_node_preds])
                                    if len(preds)==0:
                                        #return ("retval", curr_tag.function, func.name, definition.codeloc.ins_addr,  self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                                        return ("retval", self.cur_fun.addr, self.cur_fun.name,self.current_state.current_codeloc.ins_addr, self.current_state.current_codeloc.ins_addr, "No_callable_function",'empty_function_parameter')
                                
                    except Exception as e:
                        
                        print(e," error at 5717")
        '''

        if len(definition.tags) > 0:
            # print("tag is")
            # magic_graph_print(rd.dep_graph.transitive_closure(definition))
            ##curr_tag = definition.tags.pop()  # Ok just take the first one as for now.
            
            extrated_tags=definition.tags.copy()
            curr_tag = extrated_tags.pop()
            
            
            
            
            
            while True:
                if len(extrated_tags)==0:
                    break
                if type(curr_tag) == ReturnValueTag:
                    break
                curr_tag = extrated_tags.pop()
            
            if not hasattr(curr_tag, "function") :
                return None
            elif curr_tag.function is None:
                return None
            #print("hasattr(curr_tag, function)" ,  hasattr(curr_tag, "function"))
            #print("curr_tag")
            # print(curr_tag)
            if type(curr_tag) == ReturnValueTag:                
                print("ReturnValueTag")
                source_function = self.cfg.functions.floor_func(definition.codeloc.block_addr)  # function that have a source taint call (here it return check functions that  call strlen)
                #source_function = self.cfg.kb.functions.contains_addr(definition.codeloc.block_addr)
                if  source_function is None and 'block_addr' in curr_tag.metadata:  # when the defination has no codeloc
                    source_function = self.cfg.functions.floor_func(curr_tag.metadata['block_addr'])
                    
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                '''
                if hasattr(self,'transitive_funtion_name') :
                    if self.transitive_funtion_name in  transitive_set :
                        
                        if hasattr(self,"d0_token"):
                            b0=self.d0_token
                        elif self.d0.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                            bb0=self.cfg.insn_addr_to_memory_data[self.d0.codeloc.ins_addr]
                            #b0=str(bb0.content)[2:-1]
                            i=0
                            while str(self.cfg.project.loader.memory.load(bb0.addr, bb0.size+i))[bb0.size+i+1] != '\\':
                                i+=1
                            b0=str(self.cfg.project.loader.memory.load(bb0.addr, bb0.size+i-1))[2:-1]
                        else:
                            b0=self.get_strings(self.d0)
                            '''
                            b0= "not_static_string"
                            pcd0 = [d for d in self.rd_ddg_graph.predecessors(self.d0) ]
                            
                            memory_def_flag=False
                            for df in pcd0 :
                                if type(df.atom)==MemoryLocation and df.atom.addr in self.cfg.memory_data :
                                    memory_def_flag=True
                            if not memory_def_flag :
                                extended_defs=[]
                                for df in pcd0 :
                                    extended_defs.extend( [d for d in  self.rd_ddg_graph.predecessors(df)]  )
                                pcd0=extended_defs
                                
                            string_list=[]
                            for df in pcd0 :
                                if type(df.atom)==MemoryLocation and df.atom.addr in self.cfg.memory_data and self.cfg.memory_data[df.atom.addr].content is not None:
                                    bb0= self.cfg.memory_data[df.atom.addr]
                                    if bb0.content is not None :
                                        #b0=str(bb0.content)[2:-1]
                                        i=0
                                        while str(self.cfg.project.loader.memory.load(bb0.addr, bb0.size+i))[bb0.size+i+1] != '\\':
                                            i+=1
                                        b0=str(self.cfg.project.loader.memory.load(bb0.addr, bb0.size+i-1))[2:-1]
                                        string_list.append(b0)
                            if len(string_list)>1:
                                b0="#".join(string_list)
                            '''
                            
                        
                        if 'token' in curr_tag.metadata:
                            b1=curr_tag.metadata['token']
                            print(b1)
                        elif definition.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                            bb1=self.cfg.insn_addr_to_memory_data[definition.codeloc.ins_addr]
                            #b1=str(bb1.content)[2:-1]
                            i=0
                            while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                                i+=1
                            b1=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                        else:
                            b1=self.get_strings(definition)
                            '''
                            b1= "not_static_string"
                            pcd0 = self.rd_ddg_graph.predecessors(definition)
                            
                            
                            memory_def_flag=False
                            for df in pcd0 :
                                if type(df.atom)==MemoryLocation and df.atom.addr in self.cfg.memory_data :
                                    memory_def_flag=True
                            if not memory_def_flag :
                                extended_defs=[]
                                for df in pcd0 :
                                    extended_defs.extend( [d for d in  self.rd_ddg_graph.predecessors(df)]  )
                                pcd0=extended_defs
                            
                            
                            
                            try:
                                
                                for df in pcd0 :
                                    if type(df.atom)==MemoryLocation and df.atom.addr in self.cfg.memory_data:
                                        bb1= self.cfg.memory_data[df.atom.addr]
                                        if bb1.content is not None :
                                            b1=str(bb1.content)[2:-1]
                            except Exception as e :
                                pass
                            '''
                            
                        
                        
                        '''
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        
                        if b1=="not_static_string" and b0 =="not_static_string":
                            return None
                        
                        
                        '''
                        if b0=="not_static_string" :
                            import ipdb;
                            ipdb.set_trace()
                            pass
                        '''
                            
                            
                        #b0=self.cfg.insn_addr_to_memory_data[self.d0.codeloc.ins_addr]
                        #b1=self.cfg.insn_addr_to_memory_data[definition.codeloc.ins_addr]
                        taint_source_name=curr_tag.metadata['tagged_by'].split()[0]
                        
                        #<Definition {Tags:{<ReturnValueTag {Function: 0x50001c, Metadata:{'tagged_by': 'SimEngineRDVEX._handle_function_cc'}}>}, Atom:<Reg 16<4>>, Codeloc:<0x459b60 id=0x459b54[-2] contextless>}>
                        
                        
                       
                        
                        
                                                   
                        if taint_source_name.strip() in ["strtok","strchr","atoi","strspn","strtol","fork","rand","malloc"]: #not in SOURCES: 
                            return None
                        if taint_source_name.strip()  not in SOURCES and  taint_source_name.strip()  not in New_input_getters:
                            return None
                            
                        '''
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        print(f'b1={b1} and b0={b0}')
                        #print(("get2set", curr_tag.function, taint_source_name, definition.codeloc.ins_addr, reg_def.codeloc.ins_addr,source_function.name,b1,b0))
                        
                        # ins_addr
                        if  definition.codeloc.ins_addr is None  and 'ins_addr' in curr_tag.metadata: # when defination has external codeloc
                            return ("get2set", curr_tag.function, taint_source_name, curr_tag.metadata['ins_addr'], reg_def.codeloc.ins_addr,source_function.name,b1,b0)
                        
                        
                        return ("get2set", curr_tag.function, taint_source_name, definition.codeloc.ins_addr, reg_def.codeloc.ins_addr,source_function.name,b1,b0)
                        
                        
                        
                    
                #print(" we are here where are you")
                #print(curr_tag)
                try:
                    func = self.cfg.functions.get_by_addr(curr_tag.function)  # get source function name (e.g return strlen function
                    #print("I passed here 4086")
                except Exception as e:
                    print(e)
                    return None
                
                
                
                if 'token' in curr_tag.metadata:
                    b1=curr_tag.metadata['token']
                elif definition.codeloc.ins_addr  in self.cfg.insn_addr_to_memory_data :
                    bb1=self.cfg.insn_addr_to_memory_data[definition.codeloc.ins_addr]
                    #b1=str(bb1.content)[2:-1]
                    i=0
                    while str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i))[bb1.size+i+1] != '\\':
                        i+=1
                    b1=str(self.cfg.project.loader.memory.load(bb1.addr, bb1.size+i-1))[2:-1]
                else:
                    b1=self.get_strings(definition)
                    '''
                    b1= "not_static_string"
                    pcd0 = self.rd_ddg_graph.predecessors(definition)
                    
                    memory_def_flag=False
                    for df in pcd0 :
                        if type(df.atom)==MemoryLocation and df.atom.addr in self.cfg.memory_data :
                            memory_def_flag=True
                        if not memory_def_flag :
                            extended_defs=[]
                            for df in pcd0 :
                                extended_defs.extend( [d for d in  self.rd_ddg_graph.predecessors(df)]  )
                            pcd0=extended_defs
                    
                    for df in pcd0 :
                        if type(df.atom)==MemoryLocation and self.cfg.memory_data[df.atom.addr].content is not None:
                            bb1= self.cfg.memory_data[df.atom.addr]
                            if bb1.content is not None :
                                b1=str(bb1.content)[2:-1]
                    '''
                            
                    
                
               
                
                    
                
                if func.name in ["strtok","strchr","atoi","strspn","strtol","fork","rand","malloc"]: #not in SOURCES: 
                    return None
                if func.name not in SOURCES and  func.name  not in New_input_getters:
                            return None
                
                #print("I arrived here here")
                '''
                import ipdb;
                ipdb.set_trace()
                pass
                ''' 
                
                if  definition.codeloc.ins_addr is None:#  and 'ins_addr' in curr_tag.metadata: # when defination has external codeloc
                    #return ("retval", curr_tag.function, func.name,curr_tag.metadata['ins_addr'], reg_def.codeloc.ins_addr, source_function.name,b1)
                    #return ("retval", curr_tag.function, func.name,curr_tag.metadata['ins_addr'], self.current_codeloc.ins_addr, source_function.name,b1)
                    #print("retval", curr_tag.function, func.name,curr_tag.metadata['ins_addr'], self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                    other_ins_addr=0
                    if 'ins_addr' in curr_tag.metadata:
                        other_ins_addr=curr_tag.metadata['ins_addr']
                    elif 'block_addr' in curr_tag.metadata:
                        other_ins_addr=curr_tag.metadata['block_addr']
                        
                    #return ("retval", curr_tag.function, func.name,curr_tag.metadata['ins_addr'], self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                    return ("retval", curr_tag.function, func.name,other_ins_addr, self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                '''
                if definition.codeloc.ins_addr is None:
                    import ipdb;
                    ipdb.set_trace()
                    pass
                '''
                # def_explorer.current_state  , state.current_codeloc
                #b1=self.cfg.insn_addr_to_memory_data[definition.codeloc.ins_addr]
                ##return ("retval", curr_tag.function, func.name, definition.codeloc.ins_addr, reg_def.codeloc.ins_addr, source_function.name,b1)
                ###return ("retval", curr_tag.function, func.name, definition.codeloc.ins_addr,  self.current_codeloc.ins_addr, source_function.name,b1)
                #print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
                #print( hex(definition.codeloc.ins_addr), " ",  hex(self.current_state.current_codeloc.ins_addr)," ", hex(reg_def.codeloc.ins_addr))
                return ("retval", curr_tag.function, func.name, definition.codeloc.ins_addr,  self.current_state.current_codeloc.ins_addr, source_function.name,b1)
                '''
                if func.name in SOURCES:   
                    
                    return (
                        "retval", curr_tag.function, func.name, definition.codeloc.ins_addr, reg_def.codeloc.ins_addr,
                        source_function.name,b1)
                else:
                    return None
                    #return ("retval", curr_tag.function, func.name + "_notInSource", definition.codeloc.ins_addr, reg_def.codeloc.ins_addr,                        source_function.name,b1)
                    ##return None
                '''
                
            else:
                # print(type(curr_tag))
                return None

            

        
        
def test_DSE(proj,start_address,sink_addr,desired_blocks):
    input_length = 100  # Adjust based on your analysis
    #input_buf = proj.factory.BVS("input_buffer", 8 * input_length)

    # Initialize symbolic execution from a specific address
    ##start_address = 4523728  # Replace with your desired start address
    init_state = proj.factory.blank_state(addr=start_address)

    # Create a symbolic buffer using the solver's interface
    input_buf = init_state.solver.BVS("input_buffer", 8 * input_length)

    sm = proj.factory.simulation_manager(init_state)

    # Given sequence of basic blocks leading to the sink
    ##desired_blocks = [4524180,4523872,4523872,4523764,4523728]  # Replace with your addresses
    ##sink_addr =4524180# 0x450898  # Replace with your sink's address

    # Explore with guidance towards the desired blocks
    print("desired_blocks ->",desired_blocks)
    while len(sm.active) > 0:
        sm.step()
        print("***> ",[s.addr for s in sm.active ])
        sm.stashes['active'] = [s for s in sm.active if s.addr in desired_blocks]

    # Check if we reached the sink and extract constraints and input
    print("sink_addr=",sink_addr, "--> ",[s.addr for s in sm.active])
    if sink_addr in [s.addr for s in sm.active]:
        sink_state = sm.active[0]
        constraints = sink_state.solver.constraints
        print("Constraints for the path to the sink:")
        for constraint in constraints:
            print(constraint)

        input_solution = sink_state.solver.eval(input_buf, cast_to=bytes)
        print("\nPossible input that satisfies the constraints:")
        print(input_solution)
    else:
        print("Sink not reachable following the desired blocks.")

        
    
def test_sanity(project,clinic):
    
    
    myfile=open("Result_file.txt")
    #line=myfile.readline()
    
    for line in myfile:
        parts=line.split(",")
        parts[-2].split(":")[1].strip().split("#")
        desired_blocks= [ int(i,0) for i in parts[-2].split(":")[1].strip().split("#") ]
        keyword=parts[-1].split(":")[1].strip()
        
        
        print(desired_blocks)
        final_blocks_list=[]
        for addr in desired_blocks:
            if addr not in final_blocks_list :
                final_blocks_list.append(addr) 

        type_list=[]
        for addr in final_blocks_list :
            #print(addr)
            blk=get_clinic_block(project,clinic, addr)
            if blk is not None and  hasattr(blk,"statements") and len(blk.statements) >0 :
                type_list.append((addr,type(blk.statements[-1]) ) )
                
        print(keyword,type_list)        
       
    
    
    return
    import ipdb;
    ipdb.set_trace()
    pass
    
    
    
    desired_blocks = [4524180,4523872,4523872,4523764,4523728] 
    final_blocks_list=[]
    for addr in desired_blocks:
        if addr not in final_blocks_list :
            final_blocks_list.append(addr) 
    
    for addr in final_blocks_list :
        print(addr)
        blk=get_clinic_block(project,clinic, addr)
        if blk is not None and  hasattr(blk,"statements") and len(blk.statements) >0 :
            print (type(blk.statements[-1]))
        else:
            print("#############")
            block = project.factory.block(addr)
            print(block.pp() )
            
            import ipdb;
            ipdb.set_trace()
            pass
            
def extract_operands(operand, state=None):
    if type(operand)==list :
        return extract_operands(operand[0],state) + extract_operands(operand[1],state)
    if type(operand) == ailment.expression.BinaryOp :
        return extract_operands(operand.operands)
    elif type(operand) ==  ailment.expression.Const:
        return []
    elif type(operand) == ailment.expression.Register:
        return [operand]      
    elif hasattr(operand,'base') :
        atom=MemoryLocation(SpOffset(state.arch.bits,operand.offset),operand.size)
        return [atom]
    elif type(operand) == ailment.expression.Load  and  hasattr(operand,'addr') and type(operand.addr) == ailment.expression.StackBaseOffset:
        atom=MemoryLocation(SpOffset(state.arch.bits,operand.addr.offset),operand.size)
        return [atom]
    elif type(operand) == ailment.expression.Load and  hasattr(operand,'addr') and type(operand.addr) == ailment.expression.BinaryOp and type(operand.addr.operands[1])==ailment.expression.Const:
        #atom=Register(operand.addr.operands[0].reg_offset,operand.addr.operands[0].size)
        atom=MemoryLocation(SpOffset(state.arch.bits,operand.addr.operands[1].value),operand.addr.operands[1].size)
        return [atom]
    else: # just in case there is  a situation I am not aware  of
        return []
            
def get_path_between_two_nodes(node_A,node_B,function):
        reg_seen_defs = set()
        defs_to_check = [(node_A, [])]  # Use a list as a stack, storing (node, path_so_far)

        # Cache of all seen nodes (Tie the knot)
        seen_defs = set()

        paths = []  # To store all paths leading to nodes with the desired tag

        while len(defs_to_check) != 0:# defs_to_check:
            current_def, current_path = defs_to_check.pop() # here current_def is a CFG node
            seen_defs.add(current_def)
            current_path = current_path + [current_def.addr]#[current_def]

            # Check if the current Definition has a tag
            def_value = current_def == node_B 

            # If def_value is not None we hit a "retval" and we collect it,
            if def_value:
                reg_seen_defs.add(def_value)
                paths.append(current_path)
            else:
                # If we have undefined pointers (a.k.a. Top value) we need to process the predecessors.
                if current_def in function.graph.nodes():
                    for pred in current_def.predecessors():
                        if pred not in seen_defs:
                            defs_to_check.append((pred, current_path))
        if len(paths)==0:
            return []
        return paths[0]
    
def get_path(desired_blocks,def_explorer) :
        RDA_handler=def_explorer.RDA_handler
        final_blocks_list=[]
        for addr in desired_blocks:
            if addr not in final_blocks_list :
                final_blocks_list.append(addr) 
    
        
        connected_blocks=[]
        
        i=0
        not_equal=False
        while i+1 < len(final_blocks_list):
            #'''
            tmp_fun_0 = RDA_handler.cfg.functions.floor_func(final_blocks_list[i])
            tmp_fun_1 = RDA_handler.cfg.functions.floor_func(final_blocks_list[i+1])
    
            if tmp_fun_0 !=tmp_fun_1: # they are belonging to different funtions
                i+=1
                connected_blocks.append(final_blocks_list[i-1])
                continue
                
            
            node_A=tmp_fun_0.get_node(final_blocks_list[i])
            node_B=tmp_fun_0.get_node(final_blocks_list[i+1])
            i+=1
            #I added this line without investigation to remove an error
            if node_A is None or node_B is None :
                continue
            
            if node_B in node_A.predecessors() :
                connected_blocks.append(final_blocks_list[i-1])
                continue
            else:
                sub_path=get_path_between_two_nodes(node_A,node_B,tmp_fun_0)
                connected_blocks.extend(sub_path[:-1])
                #break
                
        
        #tmp_fun_0 = RDA_handler.cfg.functions.floor_func(int(0x45e71c))
        #'''
        
        for blk_addr in final_blocks_list:
            if blk_addr not in connected_blocks:
                connected_blocks.append(blk_addr)
        
        return connected_blocks
    

    
    
import networkx as nx

# Create a sample binary graph
#G = nx.Graph()
#G.add_edges_from([(1, 2), (1, 3), (4, 5), (4, 6)])

# Function to find sibling nodes in a binary graph
def find_sibling_nodes(graph, current_node):
    # Get the parent of the current node
    parents = [n for n in graph.neighbors(current_node)]
    
    # If there's no parent or more than one parent, it's not a binary graph
    if len(parents) != 1:
        return []

    # Get the siblings
    siblings = [n for n in graph.neighbors(parents[0]) if n != current_node]
    return siblings

# Example usage
#current_node = 2
#siblings = find_sibling_nodes(G, current_node)
#siblings
    
    
    
    
def connectDefination_with_sinks( function,project,def_explorer=None,desired_blocks=None,desired_definations=None,keyword=None,connected_path=None):
        RDA_handler=def_explorer.RDA_handler
        clinic=RDA_handler.dec.clinic
        connected_blocks=connected_path
        
        
        type_list=[]
        intresting_blks=[] # contianisn condtions blocks addresses
        false_blocks=[]  # contianisn false condtions blocks addresses
        path_blk=[]
        error_messges_list=[]
        
        fail2captureConditionsTime=0
        for addr in  connected_blocks:#  paths[0]+final_blocks_list :
            #print(addr)
            tmp_fun = RDA_handler.cfg.functions.floor_func(addr)
            tmp_clinic=clinic
            tmp_state=def_explorer.current_state
            blk=None
            if tmp_fun!=function:
                for item in STACK:
                    if tmp_fun==item[0]:
                        blk=get_clinic_block(project,item[2], addr)
                        tmp_clinic=item[2]
                        tmp_state=stack_item[3]
                        break
            
            else:
                blk=get_clinic_block(project,clinic, addr)
                try:
                    tmp_state=RDA_handler._analysis.get_reaching_definitions_by_node(addr,0)#
                except Exception as e:
                    tmp_state=def_explorer.current_state
                
            if blk is not None and  hasattr(blk,"statements") and len(blk.statements) >0  :
                #type_list.append((addr,type(blk.statements[-1]) ) )
                branch_type=type(blk.statements[-1]) 
                if addr in desired_blocks:
                    path_blk.append((blk,branch_type))
                    
                '''
                if branch_type ==ailment.statement.ConditionalJump :
                    import ipdb;
                    ipdb.set_trace()
                    pass
                '''
                if  branch_type not  in [ ailment.statement.Call , ailment.statement.Store , ailment.statement.Assignment ] :
                    intresting_blks.append((blk,branch_type))
                    
                    #'''
                    try:
                        if type(blk.statements[-1]) == ailment.statement.Jump : # does not have    blk.statements[-1].true_target.value                            
                            continue
                        false_block_address=blk.statements[-1].false_target.value if blk.statements[-1].true_target.value in connected_blocks else blk.statements[-1].true_target.value
                        '''
                        if false_block_address==int(0x2a90c):
                            import ipdb;
                            ipdb.set_trace()
                            pass
                        '''   
                        false_blk=get_clinic_block(project,tmp_clinic, false_block_address)
                        false_blocks.append(false_block_address)
                        #if type(false_blk.statements[-1]) == ailment.statement.Call and hasattr(false_blk.statements[-1].target,'value') and hasattr(false_blk.statements[-1],"args") and false_blk.statements[-1].args is not None and len(false_blk.statements[-1].args) ==0 :
                        
                        if type(false_blk.statements[-1]) ==ailment.statement.Return :
                            print("blk_addr =",hex(false_block_address),"  Return -> ",false_blk.statements[-1], " ", false_blk.statements[-1].tags )
                            tmp_error="return*-1"  # when message error is in a variable
                            if tmp_error not in error_messges_list:
                                error_messges_list.append(tmp_error)
                            '''
                            import ipdb;
                            ipdb.set_trace()
                            pass
                            '''
                        elif type(false_blk.statements[0]) ==  ailment.statement.Assignment  and type(false_blk.statements[0].src)==ailment.expression.Const and  false_blk.statements[0].src.value in RDA_handler.cfg.memory_data :
                                bb0 = RDA_handler.cfg.memory_data[false_blk.statements[0].src.value]
                                b0=""
                                if bb0.content is not None:
                                    # b0=str(bb0.content)[2:-1]
                                    i = 0
                                    while str(RDA_handler.cfg.project.loader.memory.load(bb0.addr, bb0.size + i))[bb0.size + i + 1] != '\\':
                                        i += 1
                                    b0 = str(RDA_handler.cfg.project.loader.memory.load(bb0.addr, bb0.size + i - 1))[2:-1]
                                    
                                tmp_error="pcvar*"+b0  # when message error is in a variable
                                if tmp_error not in error_messges_list:
                                    error_messges_list.append(tmp_error)
                                print("error function is -> ",tmp_error)
                        
                        
                        elif  type(false_blk.statements[-1]) == ailment.statement.Call and hasattr(false_blk.statements[-1],'target') and hasattr(false_blk.statements[-1].target,'value'):
                            error_function=RDA_handler.cfg.functions.get_by_addr(addr=false_blk.statements[-1].target.value)
                            b0=""
                            if error_function is not None and false_blk.statements[-1].args is not None and len(false_blk.statements[-1].args)==1 and hasattr(false_blk.statements[-1].args[0],'value') and false_blk.statements[-1].args[0].value in RDA_handler.cfg.memory_data :
                                
                                bb0 =RDA_handler.cfg.memory_data[false_blk.statements[-1].args[0].value]
                                b0=""
                                if bb0.content is not None:
                                    # b0=str(bb0.content)[2:-1]
                                    i = 0
                                    while str(RDA_handler.cfg.project.loader.memory.load(bb0.addr, bb0.size + i))[bb0.size + i + 1] != '\\':
                                        i += 1
                                    b0 = str(RDA_handler.cfg.project.loader.memory.load(bb0.addr, bb0.size + i - 1))[2:-1]
                                
                                #print(false_blk.statements[-1])
                                tmp_error=error_function.name+"*"+b0
                                if tmp_error not in error_messges_list:
                                    error_messges_list.append(tmp_error)
                                print("error function is -> ",error_function.name, "text=",b0)
                                
                            # hoping to catch exit() similar functions
                            elif error_function is not None and hasattr(false_blk.statements[-1],"args")  and false_blk.statements[-1].args is not None and len(false_blk.statements[-1].args)==1 and type(false_blk.statements[-1].args[0])==ailment.expression.Const :
                                tmp_error=error_function.name+"*"+str(false_blk.statements[-1].args[0].value )
                                if tmp_error not in error_messges_list:
                                    error_messges_list.append(tmp_error)
                                print("error function is -> ",error_function.name, "value=",b0)
                       
                                '''
                                
                                '''
                    except Exception as e:
                        print("ERROR AT 4131 ->",e)
                        continue
                        #raise e
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    #'''
                        
                if branch_type not in type_list :
                    type_list.append(branch_type ) 
                
        print(type_list)   
        print("***")
        #print(intresting_blks)
                    
        #print([hex(i) for i in paths[0]+final_blocks_list])
        
       
                 
        
        
        print("Extracted conditional Blocks")
        for itm in intresting_blks:
            if itm[1]==ailment.statement.ConditionalJump:
                print(itm[0].statements[-1].condition.verbose_op," -> ",itm[0].statements[-1].condition)
                
        
        print("########")
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        
        '''
        print("\n******  path_blk"  )
        for itm in path_blk:
            print(itm[0].statements[-1],"\n")
        '''
        flag_list=[0]  # to collect how many times a tainted defination is checked
        
        reg_name_list=[]    
            
        for item in intresting_blks:
            try:
                cnd_statement=item[0].statements[-1]
                if type(cnd_statement)!=ailment.statement.ConditionalJump:
                    continue
                # etract if there is a log error

                blk_addr=cnd_statement.tags['vex_block_addr']
            
                tmp_fun = RDA_handler.cfg.functions.floor_func(blk_addr)
                #tmp_state=def_explorer.current_state
                if tmp_fun==function :
                    tmp_state=def_explorer.current_state
                elif tmp_fun!=function:
                    for stack_item in STACK:
                        if tmp_fun==stack_item[0]:
                            tmp_state=stack_item[3]
                            break
                else:
                    tmp_state=RDA_handler._analysis.get_reaching_definitions_by_node(blk_addr,0)# state before executing the conditin
            except Exception as e:
                tmp_state=def_explorer.current_state
                print("error at 4139 ",e)
                #'''
                
                continue
                import ipdb;
                ipdb.set_trace()
                pass
                #'''
                
            operands=cnd_statement.condition.operands
            
            '''
            import ipdb;
            ipdb.set_trace()
            pass
            ''' 
                    
            
            
            operands_list=[] # to collect operands
            for oprand in operands:
                try:
                    if type(oprand) == ailment.expression.BinaryOp :
                        operands_list.extend( extract_operands(oprand.operands,tmp_state)   )
                    elif type(oprand) == ailment.expression.Const:
                        continue
                    elif type(oprand) == ailment.expression.Register :
                        operands_list.append(oprand)
                    elif hasattr(oprand,'base') :
                        atom=MemoryLocation(SpOffset(tmp_state.arch.bits,oprand.offset),oprand.size)
                        operands_list.append(atom)
                    elif type(oprand) == ailment.expression.Load  and  hasattr(oprand,'addr') and type(oprand.addr) == ailment.expression.StackBaseOffset:
                        atom=MemoryLocation(SpOffset(tmp_state.arch.bits,oprand.addr.offset),oprand.size)
                        operands_list.append(atom)
                    elif type(oprand) == ailment.expression.UnaryOp:
                        operands_list.extend( extract_operands(oprand.operands[0],tmp_state)   )
                        '''                     
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        
                        
                    else:
                        print("we did not catch it  -->  ",oprand, " -> ",type(oprand))
                    
                except Exception as e:
                    print("error AT 4248 with --> ",oprand, " -> ",type(oprand))
                    
                    continue
                    #raise(e)
                    
                    #'''
                    
                    
                    #'''
                    
                    
            for oprand in operands_list:
                try:
                    defination_checked_flag=False 
                    if type(oprand) == ailment.expression.Register:
                        atom_1=Register(oprand.reg_offset,oprand.size)
                        df1=next(iter(tmp_state.get_definitions(atom_1)  ))
                        operand_name=oprand.tags["reg_name"]
                    elif type(oprand) == MemoryLocation:
                        df1=next(iter(tmp_state.get_definitions(oprand)  ))
                        operand_name=oprand.addr
                    if df1 in desired_definations:
                        #to remove similar conditions s2<4> == 0x0<32>
                        if len(cnd_statement.condition.operands) == 2 and type(cnd_statement.condition.operands[1]) == ailment.expression.Const and cnd_statement.condition.operands[1].value== 0 :
                     
                            no_sanitization_flag=False
                            '''
                            print("here  here-> ", f'{operand_name}@{cnd_statement.condition}')
                            print(df1)
                            print([dddd for dddd in desired_definations if dddd==df1 ])
                            '''
                            extrated_tags=df1.tags.copy()
                            if len(extrated_tags)==0 :
                                prd1=[d for d in def_explorer.RDA_handler._analysis.dep_graph.predecessors(df1)]
                                for dfdf in prd1 :
                                    if dfdf in desired_definations:
                                        extrated_tags=dfdf.tags.copy()
                                        if len(extrated_tags)==0:
                                            continue
                                        curr_tag = extrated_tags.pop()
                                        while True:
                                            if len(extrated_tags)==0:
                                                break
                                            if type(curr_tag) == ReturnValueTag:
                                                break
                                            curr_tag = extrated_tags.pop()

                                        taint_source_name=curr_tag.metadata['tagged_by'].split()[0]
                                        print(taint_source_name)
                                        if taint_source_name in SOURCES or taint_source_name in New_input_getters:  #"simulation Effect" in curr_tag.metadata['tagged_by']:
                                            no_sanitization_flag=True


                            else:
                                curr_tag = extrated_tags.pop()
                                while True:
                                    if len(extrated_tags)==0:
                                        break
                                    if type(curr_tag) == ReturnValueTag:
                                        break
                                    curr_tag = extrated_tags.pop()

                                taint_source_name=curr_tag.metadata['tagged_by'].split()[0]
                                print(taint_source_name)
                                if taint_source_name in SOURCES or taint_source_name in New_input_getters:  #"simulation Effect" in curr_tag.metadata['tagged_by']:
                                    no_sanitization_flag=True
                                    



                            if not no_sanitization_flag:
                                flag_list.append(1)
                                reg_name_list.append(f'{operand_name}@{cnd_statement.condition}')
                                print(f'{operand_name}@{cnd_statement.condition}') 
                            else:
                                print(f'{operand_name}@{cnd_statement.condition}  ',curr_tag.metadata['tagged_by'])
                        
                        
                        else:
                            flag_list.append(1)
                            reg_name_list.append(f'{operand_name}@{cnd_statement.condition}')
                            
                        
                        '''                       
                        print(" hhh ->", prd1)
                        import ipdb;
                        ipdb.set_trace()
                        pass
                        '''
                        
                    elif df1 in def_explorer.RDA_handler._analysis.dep_graph.nodes():
                        check_more=False
                        prd1=[d for d in def_explorer.RDA_handler._analysis.dep_graph.predecessors(df1)]
                        for tmp_def in prd1:
                            if tmp_def in desired_definations:
                                #if len(cnd_statement.condition.operands) ==2 and type(cnd_statement.condition.operands[1]) ==ailment.expression.Const and cnd_statement.condition.operands[1].value==0 :
                                #    continue
                                flag_list.append(1)
                                reg_name_list.append(f'{operand_name}@{cnd_statement.condition}' )
                                print(tmp_def)
                                print("#### we hit here for checking time  :)")
                                check_more=True
                                continue
                                write_dot(def_explorer.RDA_handler._analysis.dep_graph.transitive_closure(tmp_def), "aa.dot")
                                os.system("dot -Tsvg -o aa.svg aa.dot")
                                import ipdb;
                                ipdb.set_trace()
                                pass
                                check_more=True
                                continue
                            else:
                                reg_def = tmp_def
                                reg_seen_defs = set()
                                defs_to_check = set()
                                defs_to_check.add(reg_def)

                                # Cache of all seen nodes (Tie the knot)
                                seen_defs = set()
                                while len(defs_to_check) != 0:
                                    current_def = defs_to_check.pop()
                                    seen_defs.add(current_def)
                                    # Check if the current Definition has a tag
                                    

                                    if current_def in desired_definations:
                                        reg_seen_defs.add(def_value)
                                        flag_list.append(1)
                                        reg_name_list.append(f'{operand_name}@{cnd_statement.condition}' )
                                        print(tmp_def, "--", current_def)
                                        print("#### we hit the second for checking time  :)")
                                    else:
                                        if current_def in def_explorer.RDA_handler._analysis.graph.nodes():
                                            for pred in def_explorer.RDA_handler._analysis.graph.predecessors(current_def):
                                                if pred not in seen_defs:
                                                    defs_to_check.add(pred)

                                
                                    
                        if not check_more: #  there intermediate definations. desired_definations have been passed into a temp prameters, then passed to a function
                            continue
                            write_dot(def_explorer.RDA_handler._analysis.dep_graph.transitive_closure(df1), "bb.dot")
                            os.system("dot -Tsvg -o bb.svg bb.dot")
                            import ipdb;
                            ipdb.set_trace()
                            pass
                            continue
                            for tmp_def in prd1:
                                prd2=[d for d in def_explorer.RDA_handler._analysis.dep_graph.predecessors(tmp_def)]
                                for tmp_def_2 in prd2:
                                    if tmp_def_2 in desired_definations:
                                        flag_list.append(1)
                                        reg_name_list.append(f'{operand_name}@{cnd_statement.condition}' )
                                        print(tmp_def)
                                        print("#### we hit the second condition for checking time  :)")
                                        #break
                            
                except Exception as e:
                    print("error ->",e)
                    print(oprand)
                    fail2captureConditionsTime+=1
                    continue
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    
                    #raise(e)
                    #continue
                    #'''
                    #raise(e)
                    
                    #'''
                    
            
        checking_time= sum(flag_list)
        conditions_str="#".join(reg_name_list)
        error_messges_str= "#".join(error_messges_list)
        if checking_time>0:
            print("checking_time =" ,checking_time, " ",conditions_str)#," -> ",cnd_statement.condition)
            
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        
        return checking_time, fail2captureConditionsTime, conditions_str,error_messges_str
           
           
                            
                
                
            
        
        #test_DSE(project,start_address=paths[0][-1],sink_addr=paths[0][0],desired_blocks=paths[0])
        
        
        #return reg_seen_defs, paths  # Return paths in addition to reg_seen_defs        
        


##########

    

def backtrack_definations(def_explorer, reg_defs, result_file, memcpy_func_pred, FUNCS, sink, memcpy_addr, check_is_tainted_def=False):
    for reg_def in reg_defs:
        OVERALL_DEFS = set()
        #magic_graph_print(rd.dep_graph.transitive_closure(reg_def))
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        function_containing_sink= def_explorer.cfg.kb.functions.floor_func(memcpy_addr)   #  hex(memcpy_addr)
        if  not function_containing_sink is None:
            function_containing_sink_name= function_containing_sink.name
        else:
            function_containing_sink_name = hex(memcpy_addr)
        

        # magic_graph_print(rd.dep_graph.transitive_closure(reg_def))
        reg_seen_defs, Paths,visited_functions = def_explorer.resolve_use_def(reg_def)
        #for definition in reg_seen_defs:
        #    OVERALL_DEFS.add(definition)
        #print("Are we here")
        
        # if check_is_tainted_def:
        #     return reg_seen_defs, Paths,visited_functions
        
        
        
        
        '''
        import ipdb;
        ipdb.set_trace()
        pass
        '''
        
        for overall_def, path,visited_function in zip(reg_seen_defs,Paths,visited_functions) :# OVERALL_DEFS: 
            print(overall_def)
            print("path ->",path)
            print(visited_function)
            print("$$$$$$$$$$$$$$$$$$$")
            if overall_def[0] == "get2set":
                #str_path="#".join([str(hex(i)) for i in  path])
                tmp_path=[i.codeloc.block_addr for i in path ]
                str_path="#".join([str(hex(i)) for i in  tmp_path])
                connected_path=get_path(desired_blocks=tmp_path,def_explorer=def_explorer)
                
                #print("connected_path -> ",connected_path)
                print("visited_function ->",visited_function)
                tmp_visited_function=[]
                length_visited_function=[] # for strncpy and similar functions
                for vfn in visited_function :
                    
                    if vfn[1] in connected_path and vfn[2]!=-1:
                        length_str=f'{vfn[0]}*{vfn[2]}' 
                        if length_str not in length_visited_function:
                            length_visited_function.append(length_str)
                            
                    if vfn not in tmp_visited_function and vfn[1] in connected_path :
                        tmp_visited_function.append(vfn)
                tmp_visited_function=[fn[0] for fn in tmp_visited_function]
                str_visited_fnctions="#".join(tmp_visited_function)#[fn for fn in  visited_function])
                str_length_visited_function="#".join(length_visited_function)
                print(" \n get2set keyword is -> ", overall_def[6])
                print("str_visited_fnctions -> ", str_visited_fnctions,tmp_visited_function)
                try:
                    checking_time, fail2captureConditionsTime,conditions_str, error_messges_str=connectDefination_with_sinks(function=def_explorer.RDA_handler.cur_fun, project=def_explorer.RDA_handler._analysis.project,def_explorer=def_explorer, desired_blocks=tmp_path,desired_definations=path, keyword=overall_def[6],connected_path=connected_path)
                except Exception as e:
                    #raise e
                    checking_time,fail2captureConditionsTime, conditions_str, error_messges_str=-1,-1,"",""
                        
                
                
                #print("do an error happend here 1")
                
                #print(f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name} ,  Source_name: {overall_def[5]} ,  source_insr_addr : {hex(overall_def[3])},  Source_addr: {hex(overall_def[1])} ,  taint_Source: {overall_def[2]} , sink_insr_add : {hex(overall_def[4])}  ,Sink_addr: {function_containing_sink_name} ,  Sink_name: {sink},  checking_time:{checking_time},  conditions_str:{conditions_str} ,  visited_fnctions : {str_visited_fnctions}, fail2captureConditionsTime: {fail2captureConditionsTime}, error_messges_str : {error_messges_str}, str_length_visited_function : {str_length_visited_function} , path : {str_path} , {overall_def[6]} , {overall_def[7]}  \n')
                
                
                result_file.write(f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name} ,  Source_name: {overall_def[5]} ,  source_insr_addr : {hex(overall_def[3])},  Source_addr: {hex(overall_def[1])} ,  taint_Source: {overall_def[2]} , sink_insr_add : {hex(overall_def[4])}  ,Sink_addr: {function_containing_sink_name} ,  Sink_name: {sink},  checking_time:{checking_time},  conditions_str:{conditions_str} ,  visited_fnctions : {str_visited_fnctions}, fail2captureConditionsTime: {fail2captureConditionsTime}, error_messges_str : {error_messges_str}, str_length_visited_function : {str_length_visited_function} , path : {str_path} , {overall_def[6]} , {overall_def[7]}  \n')
                result_file.flush()
                
                
                
                '''
                if overall_def[6]=="wan_netmask":
                    connectDefination_with_sinks(function=def_explorer.RDA_handler.cur_fun, project=def_explorer.RDA_handler._analysis.project,def_explorer=def_explorer, desired_blocks=tmp_path,desired_definations=path)
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    
                '''
                
            if overall_def[0] == "retval":
                # It's not always guaranteed that the retval tag of a overall_def has the
                # func addr, in those casese we call it a day (overall_def[1]   be None).
                if overall_def[1] != None:
                    '''
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    '''
                    # FUNCS.add(overall_def[1])
                    # FUNCS.add((overall_def[1],overall_def[2]))
                    tmp_path=[i.codeloc.block_addr for i in path ]
                    str_path="#".join([str(hex(i)) for i in  tmp_path])
                    
                    
                    connected_path=get_path(desired_blocks=tmp_path,def_explorer=def_explorer)
                
                    print("connected_path -> ",connected_path)
                    print("visited_function ->",visited_function)
                    tmp_visited_function=[]
                    length_visited_function=[] # for strncpy and similar functions
                    for vfn in visited_function :
                        
                        if vfn[1] in connected_path and vfn[2]!=-1:
                            length_str=f'{vfn[0]}*{vfn[2]}' 
                            if length_str not in length_visited_function:
                                length_visited_function.append(length_str)
                        
                        if vfn not in tmp_visited_function and vfn[1] in connected_path :
                            tmp_visited_function.append(vfn)
                    tmp_visited_function=[fn[0] for fn in tmp_visited_function]
                    str_visited_fnctions="#".join(tmp_visited_function)#[fn for fn in  visited_function])
                    str_length_visited_function="#".join(length_visited_function)
                    
                    '''
                    tmp_visited_function=[]
                    for vfn in visited_function :
                        if vfn not in tmp_visited_function:
                            tmp_visited_function.append(vfn)
                    str_visited_fnctions="#".join(tmp_visited_function)#[fn for fn in  visited_function])
                    '''
                    print(" \n keyword is -> ", overall_def[6])
                    print("str_visited_fnctions -> ", str_visited_fnctions)
                    try:
                        checking_time, fail2captureConditionsTime, conditions_str, error_messges_str=connectDefination_with_sinks(function=def_explorer.RDA_handler.cur_fun, project=def_explorer.RDA_handler._analysis.project,def_explorer=def_explorer, desired_blocks=tmp_path,desired_definations=path, keyword=overall_def[6],connected_path=connected_path)
                        
                    except Exception as e:
                        checking_time,fail2captureConditionsTime, conditions_str, error_messges_str=-1,-1,"",""
                        #raise e
                       
                    '''    
                    print("do an error happend here 2")
                    try:
                        print( f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name} ,  Source_name: {overall_def[5]} ,  source_insr_addr : {hex(overall_def[3])},  Source_addr: {hex(overall_def[1])} ,  taint_Source: {overall_def[2]} , sink_insr_add : {hex(overall_def[4])}  ,Sink_addr: {function_containing_sink_name} ,  taint_Sink: {sink},  checking_time:{checking_time},  conditions_str:{conditions_str} ,  visited_fnctions : {str_visited_fnctions}, fail2captureConditionsTime: {fail2captureConditionsTime}, error_messges_str : {error_messges_str} , str_length_visited_function : {str_length_visited_function} ,  path : {str_path} , keyword: {overall_def[6]}  \n')
                    except Exception as e:
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    '''
                    result_file.write(
                        f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name} ,  Source_name: {overall_def[5]} ,  source_insr_addr : {hex(overall_def[3])},  Source_addr: {hex(overall_def[1])} ,  taint_Source: {overall_def[2]} , sink_insr_add : {hex(overall_def[4])}  ,Sink_addr: {function_containing_sink_name} ,  taint_Sink: {sink},  checking_time:{checking_time},  conditions_str:{conditions_str} ,  visited_fnctions : {str_visited_fnctions}, fail2captureConditionsTime: {fail2captureConditionsTime}, error_messges_str : {error_messges_str} , str_length_visited_function : {str_length_visited_function} ,  path : {str_path} , keyword: {overall_def[6]}  \n')
                    result_file.flush()
                    
                    '''
                    if overall_def[6]=="management_link":
                        connectDefination_with_sinks(function=def_explorer.RDA_handler.cur_fun, project=def_explorer.RDA_handler._analysis.project,def_explorer=def_explorer, desired_blocks=tmp_path,desired_definations=path)
                        import ipdb;
                        ipdb.set_trace()
                        pass
                    '''
                        
                    #FUNCS.append({'target': memcpy_func_pred.name, 'source': overall_def[2], 'sink': sink})
                    '''
                    #magic_graph_print(def_explorer.rd_ddg_graph.transitive_closure(reg_def))
                    import ipdb;
                    ipdb.set_trace()
                    pass
                    '''


                    
'''                    
import subprocess
import signal

class TimeoutError(Exception):
    pass

def timeout_handler(signum, frame):
    raise TimeoutError("Function call timed out")

def run_function_with_timeout(function, args=(), kwargs={}, timeout=10):
    signal.signal(signal.SIGALRM, timeout_handler)
    signal.alarm(timeout)
    try:
        result = function(*args, **kwargs)
    finally:
        signal.alarm(0)
    return result


'''




def my_function(proj,memcpy_func_pred,handler,cfg,visited_file):
    # code that may take a long time to run   
    handler.set_current_fucntion(memcpy_func_pred)
    handler.set_call_graph(cfg.functions.callgraph)
    handler.set_start_function(memcpy_func_pred)
    
    
    
    start_time = datetime.datetime.now()
    try:
        memcpy_addr = memcpy_func_pred.addr  
        if 1==1:# memcpy_addr not in Analyzed_Before:
            # Get CFG node for memcpy
            memcpy_node = cfg.model.get_any_node(memcpy_addr)
            # Get all the XRefs (predecessor of the memcpy nodes)
            memcpy_node_preds = memcpy_node.predecessors
            # Grab all functions that have an xrefs to the basic function
            memcpy_funcs_preds = list(set([x.function_address for x in memcpy_node_preds]))
            dec = proj.analyses.Decompiler(memcpy_func_pred, cfg=cfg)
            ##if len(memcpy_funcs_preds)>0:        
            ##    Analyzed_Before[memcpy_addr]=dec
        ##else:
        ##    dec= Analyzed_Before[memcpy_addr]
        
        
        clinic=dec.clinic
        
        
        handler.set_clinic(clinic)
        handler.set_dec(dec)
    except Exception as e :
        handler.set_clinic(None)
        handler.set_dec(None)
    #print((memcpy_func_pred, dec, clinic))
    #STACK.append((memcpy_func_pred, dec, clinic))
    if memcpy_func_pred.name =="sub_a228":
        print("sub_a228")
    if memcpy_func_pred.name =="memcpy":
        print("memcpy")
    if memcpy_func_pred.name =="sub_fbdc":
        print("sub_fbdc")
    if memcpy_func_pred.name =="sub_dad4":
        print("sub_dad4")
    rd = proj.analyses.ReachingDefinitions(subject=memcpy_func_pred,
                                              func_graph=memcpy_func_pred.graph,
                                              cc=memcpy_func_pred.calling_convention,
                                              dep_graph=dep_graph.DepGraph(), function_handler=handler,observe_all=True
                                              )
    end_time = datetime.datetime.now()
    print("passed_time --> "+",{}s".format((end_time -start_time).seconds))
    handler.get_visited_file().write(",{}s".format((end_time - start_time).seconds))
    handler.get_visited_file().flush()
    #visited_file.write(",{}s".format((start_time-end_time).seconds))
    
'''    
import multiprocessing

class TimeoutError(Exception):
    pass

def worker_function(queue, function, args, kwargs):
    try:
        result = function(*args, **kwargs)
        queue.put(('success', result))
    except Exception as e:
        queue.put(('error', e))

def run_function_with_timeout(function, args=(), kwargs={}, timeout=10):
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=worker_function, args=(q, function, args, kwargs))
    p.start()
    p.join(timeout=timeout)
    
    if p.is_alive():
        p.terminate()
        p.join()  # Ensure the process has fully terminated
        raise TimeoutError("Function call timed out")
    
    # Retrieve result or exception from queue
    status, data = q.get()
    if status == 'success':
        return data
    elif status == 'error':
        raise data

# Your my_function code remains unchanged.

#result = run_function_with_timeout(my_function, args=(project, memcpy_func_pred, handler, cfg), timeout=10000)
    
'''

import multiprocessing
import queue  # This import is necessary for handling queue.Empty exception
class TimeoutError(Exception):
    pass

def worker_function(queue, function, args, kwargs):
    try:
        result = function(*args, **kwargs)
        queue.put(('success', result))
    except Exception as e:
        queue.put(('error', e))

def run_function_with_timeout(function, args=(), kwargs={}, timeout=10):
    """ 使用单线程的方式实现超时控制 """
    q = queue.Queue()
    thread = threading.Thread(target=worker_function, args=(q, function, args, kwargs))
    thread.start()
    thread.join(timeout=timeout)

    if thread.is_alive():
        raise TimeoutError("Function call timed out")

    # 尝试从队列获取结果
    try:
        status, data = q.get(timeout=1)  # 1秒超时，防止队列阻塞
    except queue.Empty:
        raise TimeoutError("Failed to retrieve function result")

    if status == 'success':
        return data
    elif status == 'error':
        raise data

# Your my_function code remains unchanged.

#result = run_function_with_timeout(my_function, args=(project, memcpy_func_pred, handler, cfg), timeout=10000)

    
    
    
    
import lief    
def check_imported_library(elf_filename, target_library="libnvram.so"):
    transitive_set_AA=["SetValue", 'nvram_set', 'nvram_safe_set', 'nvram_pf_set', 'artblock_set',  'acos_nvram_set', 'acosNvramConfig_set', 'acosNvramConfig_write', 'envz_add', 'config_set', 'uciSet', 'device_set_string_value', 'wpa_config_set', 'scfgmgr_set_by_index_D7000', 'acosUciConfig_set', 'OM_ValSet', 'CAL_abstract_set']
    SINKS_AA =[]# ['system', '___system', 'bstar_system', 'doSystemCmd', 'doShell', 'twsystem', 'CsteSystem', 'wl_exec_cmd', "sh", "doSystem"]
    SOURCES_AA = ["NK_query_entry_get","webGetVarString","bcm_nvram_get","GetValue","webGetVarString","webGetVarString","bcm_nvram_get","GetValue","acosNvramConfig_read",'get_cgi',"websGetVar",'nvram_get', 'nvram_safe_get', 'nvram_default_get', 'nvram_pf_get', 'acosNvramConfig_get', 'config_get','wpa_config_get',  'httpGenListDataGet',  'cJSON_GetArrayItem', 'wpa_config_set', 'DoHardwareComponent',  'device_get_string_value', 'cJSON_Parse', 'uciSet', 'OM_ValGet', 'acosUciConfig_get',  'CAL_abstract_get',  'json_object_object_get', "json_object_object_get_ex", 'json_tokener_parse', 'get_wlan_setting', 'av_dict_get', 'cgi_value',  'cJSON_GetObjectItem', 'sw_getValueByName', 'value_parser_by_index_D7000', 'getoption', 'WEB_GetVar',  'av_opt_get', 'paramValueFromObjGet',  'help_getObjPtr', 'av_metadata_get',  'httpGetEnv']#,"gets","fgets", "recvfrom", "recvmsg", "recvmsg"]
    try:
        binary = lief.parse(elf_filename)

        if binary is None:
            print(f"Error: Could not parse {elf_filename}")
            return False

        # Check if the binary imports the target library
        imported_libraries = [lib.lower() for lib in binary.libraries]
        Nvram_flag=False
        if target_library.lower() in imported_libraries:
            #print(os.path.basename(elf_filename)  ," ",target_library + " is available" )
            Nvram_flag= True
            return True
            
        # Iterate through the symbols
        matched_function=[]
        functions_names= [symbol.name for symbol in  binary.symbols if symbol.type == lief.ELF.SYMBOL_TYPES.FUNC]
        for fn in SOURCES_AA + transitive_set_AA+ SINKS_AA:
            if fn in functions_names:
                matched_function.append(fn)
                #print(fn)
        if len(matched_function) >0 :#and Nvram_flag:
            #print(os.path.basename(elf_filename)  ," ",matched_function ," Nvram_flag ->",Nvram_flag)
            return True
        
    except lief.parser.error as e:
        return False
        #print(f"Error parsing {elf_filename}: {e}")    
    return False
   
#match_dictionary={'tew632_vB32': 'tew632_vB32.txt', 'US_WH450AV1BR_WH450A_V1.0.0.18': 'US_WH450AV1BR_V1.0.0.18.txt', 'DIR652B1_FW200B40': 'DIR625B1_FW200B40.txt', 'DIR823GA1_FW102B03': 'DIR823GA1_FW102B03.txt', 'NC260_1.5.2': 'NC260_v1_5_2.txt', 'US_AC10V1.0RTL_V15.03.06.23': 'US_AC10V1.0RTL_V15.03.06.23.txt', 'rv130_v44': 'rv130_1_0_3_44.txt', 'US_AC9V1.0BR_V15.03.05.14': 'US_AC9V1.0BR_httpd_V15.03.05.14.txt', 'dir825_v210': 'dir825_vB210.txt', 'R6400-V1.0.1.46': 'R6400_v1_0_2_46.txt', 'rv320_v4_4_20': 'rv320_v4_4_20.txt', 'tew827_v204': 'tew827_v204.txt'}
def get_base_address(binaryFileName):
    if "emtaint" in binaryFileName:
        jsonFiles_directory="/home/jovyan/work/firmware_vr/base_address_infected_functions_detail/"
    elif "SaTC" in binaryFileName :
        jsonFiles_directory="/home/jovyan/work/firmware_vr/satc_baseaddress/" 
    base_address_file=binaryFileName.split("/")
    file_path=os.path.join(jsonFiles_directory,base_address_file[-4]+"__"+base_address_file[-1]+".txt")    
    with open(file_path, 'r') as file:
         data = file.read()
    base_address=data.split(":")[1].strip()
    return hex(int(base_address,16))




def get_functions_to_analyse(sources,project,cfg):
    observation_points_dictionary = {}
    FUNC_PREDECESSORS = {}
    FUNC_observation_points = {}
    for sink in sources: # SOURCES:  # SINKS:
                # Address of memcpy function.
                memcpy_function = project.kb.functions.function(name=sink)
                # check if Sink is exists in the binary
                if memcpy_function is None:
                    continue
                memcpy_addr = memcpy_function.addr  # 0xf647

                # Get CFG node for memcpy
                memcpy_node = cfg.model.get_any_node(memcpy_addr)
                # Get all the XRefs (predecessor of the memcpy nodes)
                memcpy_node_preds = memcpy_node.predecessors
                # Get the CC of memcpy
                # memcpy_cc = project.kb.functions[memcpy_addr].calling_convention

                # Grab all functions that have an xrefs to the basic function
                memcpy_funcs_preds = list(set([x.function_address for x in memcpy_node_preds]))

                # Creating a dictionary of predecessors functions and the address
                # of the xrefs to the memcpy
                ##FUNC_PREDECESSORS = {}
                for memcpy_func_pred_addr in memcpy_funcs_preds:
                    FUNC_PREDECESSORS[str(memcpy_func_pred_addr)] = []
                for x in memcpy_node_preds:
                    FUNC_PREDECESSORS[str(x.function_address)].append(x)

                OVERALL_DEFS = set()
                
                

                for memcpy_func_pred_addr, xrefs in FUNC_PREDECESSORS.items():#因为一个系系欸但对应多个
                    memcpy_func_pred_addr = int(memcpy_func_pred_addr)

                    observation_points_list = []

                    for xref in xrefs:
                        # print("-->Analyzing XRefs at {}".format(hex(xref.addr)))
                        # Get the Function object of the func containing the xref to memcpy
                        memcpy_func_pred = cfg.functions.get_by_addr(memcpy_func_pred_addr)
                        # memcpy_func_pred = project.kb.functions.get_by_addr(memcpy_func_pred_addr)
                        # print(memcpy_func_pred.name)

                        # Call to the bf function is the last instruction of the block.
                        call_to_xref_address = project.factory.block(xref.addr).instruction_addrs[-1]
                        observation_points_list.append(("insn", call_to_xref_address, 0))
                        observation_points_dictionary[("insn", call_to_xref_address, 0)] = sink

                        # print(f'xref={xref}, function name = {memcpy_func_pred.name}')
                        # continue

                    if memcpy_func_pred_addr not in FUNC_observation_points:
                        FUNC_observation_points[memcpy_func_pred_addr] = observation_points_list
                    else:
                        FUNC_observation_points[memcpy_func_pred_addr].extend(observation_points_list)

    sink = None
    memcpy_addr = None
    return FUNC_PREDECESSORS
            
def analyze_selective_functions(binaryFileName,visited_file_name,visited_function_list,scond_step_candidate_result_directory):
            instance= os.path.basename(binaryFileName)
            sample= binaryFileName.split('/')[-4]
            Result_file_name = os.path.join(scond_step_candidate_result_directory + sample, f'{instance}.txt')
            #if os.path.exists(Result_file_name):
            #    continue
            result_file = open(Result_file_name, 'a+')
            
            get2set_file_name=os.path.join (scond_step_candidate_result_directory + sample, f'get2set_{instance}.txt') #('get2set_file.txt') 
            get2set_file = open(get2set_file_name, 'a+')

            Error_file_name = os.path.join(scond_step_candidate_result_directory + sample, f'error_{instance}.txt')
            
            
            visited_file = open(visited_file_name, 'a+')
            Error_file = open(Error_file_name, 'a+')
            start_time = datetime.datetime.now()

            ret_sites = {}

            #output = subprocess.run(['file', binaryFileName], stdout=subprocess.PIPE)
            
            #if not "MIPS" in f'{output}':
            #    break

            print(binaryFileName)
            #continue
            try:
                base_address = get_base_address(binaryFileName)# 0x8000#0x1000000
                #project = angr.Project(binaryFileName, auto_load_libs=False,  load_options={'main_opts': {'base_addr': base_address}})
                project = angr.Project(binaryFileName, auto_load_libs=False,  use_sim_procedures=True, default_analysis_mode='symbolic',load_options={'auto_load_libs': False,'main_opts': {'base_addr': base_address}})
                #project = angr.Project(binaryFileName, auto_load_libs=False,  use_sim_procedures=True, default_analysis_mode='symbolic',load_options={'auto_load_libs': False})
                r_ = project.analyses.CompleteCallingConventions(recover_variables=True, analyze_callsites=True)
                cfg = project.analyses.CFG(resolve_indirect_jumps=True, cross_references=True,
                                           force_complete_scan=False,
                                           normalize=True, symbols=True, data_references=True)
                

            except Exception as e:
                #print("error happend")
                #print(binaryFileName)
                #print(e)
                #raise e
                visited_file.write("cfg fialier \nDone"+" \n")
                return
                #continue

            
            #print("starting the job")
            Analyzed_Before.clear()
            handler = MyHandler()
            handler.set_cfg(cfg)
            handler.set_result_file(result_file)
            handler.set_get2set_file(get2set_file) 
            handler.set_visited_file(visited_file)
            proj=project
            
            
            
            for memcpy_func_pred_addr in addresses:
                visitied_function_Counter+=1
                memcpy_func_pred_addr = int(memcpy_func_pred_addr)
                memcpy_func_pred = cfg.functions.get_by_addr(memcpy_func_pred_addr)
                #project.analyses.VariableRecoveryFast(memcpy_func_pred)
                print("***********************************")
                print("Now analyzing predecessor {} at {}".format(memcpy_func_pred.name, hex(memcpy_func_pred_addr)))
                print("XRefs are {}".format((xrefs)))

                
                visited_function_list.append(memcpy_func_pred.name)
                handler.set_current_fucntion(memcpy_func_pred)
                visited_file.write("\n"+memcpy_func_pred.name )
                
                visited_file.flush()
                #continue
                STACK.clear()
                handler.set_call_graph(cfg.functions.callgraph)
                handler.set_start_function(memcpy_func_pred)
                
                try:
                    result = run_function_with_timeout(my_function, args=(project,memcpy_func_pred,handler,cfg,visited_file), timeout=20000)
                except TimeoutError:
                    print("Function call timed out")
                except Exception as e:
                    #print("error hapend here")
                    print(e)
                    
                    
                    Error_file.write(
                        f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name}, errorMessage: {e} \n')  # , Sink_id: {hex(memcpy_addr)} ,  Sink_name: {sink}  \n')
                    Error_file.flush()
                    continue



def analyze_binary(binaryFileName,visited_file_name,visited_function_list,scond_step_candidate_result_directory):
            instance= os.path.basename(binaryFileName)
            sample= binaryFileName.split('/')[-4]
            
            
            '''
            if not os.path.exists(f'/home/jovyan/work/firmware_vr/missed_incidiences/{sample}'):
                #return
                function_address=[]
            else:
                with open(f'{"/home/jovyan/work/firmware_vr/missed_incidiences/"}{sample}',"r") as file:
                     address=file.read().split("\n")
                function_address=[int(d,16)  for d in address if d!='']
            
            '''
            function_address=[]
            Result_file_name = os.path.join(scond_step_candidate_result_directory + sample, f'{instance}.txt')
            #if os.path.exists(Result_file_name):
            #    continue
            result_file = open(Result_file_name, 'a+')
            
            get2set_file_name=os.path.join (scond_step_candidate_result_directory + sample, f'get2set_{instance}.txt') #('get2set_file.txt') 
            get2set_file = open(get2set_file_name, 'a+')

            Error_file_name = os.path.join(scond_step_candidate_result_directory + sample, f'error_{instance}.txt')
            
            
            visited_file = open(visited_file_name, 'a+')
            Error_file = open(Error_file_name, 'a+')
            start_time = datetime.datetime.now()

            ret_sites = {}
            
            
            
            
            
            ## to be removed
            
            
            
            
            

            #output = subprocess.run(['file', binaryFileName], stdout=subprocess.PIPE)
            
            #if not "MIPS" in f'{output}':
            #    break

            print(binaryFileName)
            #continue
            try:
                #base_address = get_base_address(binaryFileName)# 0x8000#0x1000000
                #project = angr.Project(binaryFileName, auto_load_libs=False,  load_options={'main_opts': {'base_addr': base_address}})
                #project = angr.Project(binaryFileName, auto_load_libs=False,  use_sim_procedures=True, default_analysis_mode='symbolic',load_options={'auto_load_libs': False,'main_opts': {'base_addr': base_address}})
                project = angr.Project(binaryFileName, auto_load_libs=False,  use_sim_procedures=True, default_analysis_mode='symbolic',load_options={'auto_load_libs': False,'main_opts': {'custom_base_addr': 0x0}}) 
                r_ = project.analyses.CompleteCallingConventions(recover_variables=True, analyze_callsites=True)
                cfg = project.analyses.CFG(resolve_indirect_jumps=True, cross_references=True,
                                           force_complete_scan=False,
                                           normalize=True, symbols=True, data_references=True)
                

            except Exception as e:
                print("error happend")
                print(binaryFileName)
                print(e)
                #raise e
                visited_file.write("cfg fialier \nDone"+" \n")
                return
                #continue

            #print("starting the job")
            Analyzed_Before.clear()
            handler = MyHandler()
            handler.set_cfg(cfg)
            handler.set_result_file(result_file)
            handler.set_get2set_file(get2set_file) 
            handler.set_visited_file(visited_file)
            proj=project

            #------------
            
            ##observation_points_dictionary = {}
            ##FUNC_PREDECESSORS = {}
            ##FUNC_observation_points = {}
            
            
            FUNC_PREDECESSORS=get_functions_to_analyse(SOURCES + SINKS + transitive_set,project,cfg)
            
           
            
            
            # for memcpy_func_pred_addr in function_address:
            #     memcpy_func_pred_addr = int(memcpy_func_pred_addr)
            #     memcpy_func_pred = cfg.functions.floor_func(memcpy_func_pred_addr) #cfg.functions.get_by_addr(memcpy_func_pred_addr)
            #     if memcpy_func_pred is not None and  memcpy_func_pred.name in visited_function_list :
            #         visited_function_list.remove(memcpy_func_pred.name)
            
            '''

            for sink in SOURCES + SINKS + transitive_set: # SOURCES:  # SINKS:
                # Address of memcpy function.
                memcpy_function = project.kb.functions.function(name=sink)
                # check if Sink is exists in the binary
                if memcpy_function is None:
                    continue
                memcpy_addr = memcpy_function.addr  # 0xf647

                # Get CFG node for memcpy
                memcpy_node = cfg.model.get_any_node(memcpy_addr)
                # Get all the XRefs (predecessor of the memcpy nodes)
                memcpy_node_preds = memcpy_node.predecessors
                # Get the CC of memcpy
                memcpy_cc = project.kb.functions[memcpy_addr].calling_convention

                # Grab all functions that have an xrefs to the basic function
                memcpy_funcs_preds = list(set([x.function_address for x in memcpy_node_preds]))

                # Creating a dictionary of predecessors functions and the address
                # of the xrefs to the memcpy
                ##FUNC_PREDECESSORS = {}
                for memcpy_func_pred_addr in memcpy_funcs_preds:
                    FUNC_PREDECESSORS[str(memcpy_func_pred_addr)] = []
                for x in memcpy_node_preds:
                    FUNC_PREDECESSORS[str(x.function_address)].append(x)

                OVERALL_DEFS = set()
                
                

                for memcpy_func_pred_addr, xrefs in FUNC_PREDECESSORS.items():
                    memcpy_func_pred_addr = int(memcpy_func_pred_addr)

                    observation_points_list = []

                    for xref in xrefs:
                        # print("-->Analyzing XRefs at {}".format(hex(xref.addr)))
                        # Get the Function object of the func containing the xref to memcpy
                        memcpy_func_pred = cfg.functions.get_by_addr(memcpy_func_pred_addr)
                        # memcpy_func_pred = project.kb.functions.get_by_addr(memcpy_func_pred_addr)
                        # print(memcpy_func_pred.name)

                        # Call to the bf function is the last instruction of the block.
                        call_to_xref_address = project.factory.block(xref.addr).instruction_addrs[-1]
                        observation_points_list.append(("insn", call_to_xref_address, 0))
                        observation_points_dictionary[("insn", call_to_xref_address, 0)] = sink

                        # print(f'xref={xref}, function name = {memcpy_func_pred.name}')
                        # continue

                    if memcpy_func_pred_addr not in FUNC_observation_points:
                        FUNC_observation_points[memcpy_func_pred_addr] = observation_points_list
                    else:
                        FUNC_observation_points[memcpy_func_pred_addr].extend(observation_points_list)

            sink = None
            memcpy_addr = None
            '''
            
            #print("we are here")
            visitied_function_Counter=0
            
            for memcpy_func_pred_addr, xrefs in FUNC_PREDECESSORS.items():
                visitied_function_Counter+=1
                memcpy_func_pred_addr = int(memcpy_func_pred_addr)
                memcpy_func_pred = cfg.functions.get_by_addr(memcpy_func_pred_addr)
                #project.analyses.VariableRecoveryFast(memcpy_func_pred)
                print("***********************************")
                print("Now analyzing predecessor {} at {}".format(memcpy_func_pred.name, hex(memcpy_func_pred_addr)))
                print("XRefs are {}".format((xrefs)))

                ##observation_points_list = FUNC_observation_points[memcpy_func_pred_addr]
                
                # if memcpy_func_pred.name in visited_function_list :
                #     continue
                # if  memcpy_func_pred.name=="sub_67888":
                #     continue
                visited_function_list.append(memcpy_func_pred.name)
                handler.set_current_fucntion(memcpy_func_pred)
                visited_file.write("\n"+memcpy_func_pred.name )
                #print(memcpy_func_pred.name)
                #continue
                #visited_file.write(memcpy_func_pred.name + " -> "+ ",".join(syscall_within_fucnction) + " \n")
                visited_file.flush()
                #continue
                STACK.clear()
                handler.set_call_graph(cfg.functions.callgraph)
                handler.set_start_function(memcpy_func_pred)
                
                try:
                    result = run_function_with_timeout(my_function, args=(project,memcpy_func_pred,handler,cfg,visited_file), timeout=20000)
                except TimeoutError:
                    print("Function call timed out")
                except Exception as e:
                    #print("error hapend here")
                    print(e)
                    
                    
                    Error_file.write(
                        f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name}, errorMessage: {e} \n')  # , Sink_id: {hex(memcpy_addr)} ,  Sink_name: {sink}  \n')
                    Error_file.flush()
                    continue
                
            # to check if we have tested all expected functionsfreeeefreeeee
            
            if visitied_function_Counter==len(FUNC_PREDECESSORS):
                FUNC_PREDECESSORS=get_functions_to_analyse(New_input_getters,project,cfg)
                for memcpy_func_pred_addr, xrefs in FUNC_PREDECESSORS.items():
                    visitied_function_Counter+=1
                    memcpy_func_pred_addr = int(memcpy_func_pred_addr)
                    memcpy_func_pred = cfg.functions.get_by_addr(memcpy_func_pred_addr)
                    #project.analyses.VariableRecoveryFast(memcpy_func_pred)
                    print("***********************************")
                    print("Now analyzing predecessor {} at {}".format(memcpy_func_pred.name, hex(memcpy_func_pred_addr)))
                    print("XRefs are {}".format((xrefs)))

                    ##observation_points_list = FUNC_observation_points[memcpy_func_pred_addr]

                    if memcpy_func_pred.name in visited_function_list :
                        continue
                    visited_function_list.append(memcpy_func_pred.name)
                    handler.set_current_fucntion(memcpy_func_pred)
                    visited_file.write("\n"+memcpy_func_pred.name )
                    #print(memcpy_func_pred.name)
                    #continue
                    #visited_file.write(memcpy_func_pred.name + " -> "+ ",".join(syscall_within_fucnction) + " \n")
                    visited_file.flush()
                    #continue
                    STACK.clear()
                    handler.set_call_graph(cfg.functions.callgraph)
                    handler.set_start_function(memcpy_func_pred)

                    try:
                        result = run_function_with_timeout(my_function, args=(project,memcpy_func_pred,handler,cfg,visited_file), timeout=20000)
                    except TimeoutError:
                        print("Function call timed out")
                    except Exception as e:
                        #print("error hapend here")
                        print(e)


                        Error_file.write(
                            f'target_addr: {hex(memcpy_func_pred.addr)} ,  target_name: {memcpy_func_pred.name}, errorMessage: {e} \n')  # , Sink_id: {hex(memcpy_addr)} ,  Sink_name: {sink}  \n')
                        Error_file.flush()
                        continue   
                
                visited_file.write("\n Done"+" \n")
                
                
                
                
                
                end_time = datetime.datetime.now()
                visited_file.write("Total time : {}s \n".format((end_time -start_time).seconds))
    
    

#New_input_getters

def scnd_main(first_step_candidate_result_directory,scond_step_candidate_result_directory):
    #first_step_candidate_result_directory = "/home/jovyan/work/firmware_vr/Results/"
    #scond_step_candidate_result_directory = "/home/jovyan/work/firmware_vr/B_checkALL_AfterEmtaint_sanityCheck_inter_44_clinic/"
    #for_prallal_result_directory = "/home/jovyan/work/firmware_vr/44_prallel_B_checkALL_AfterEmtaint_ourdata_sanityCheck_inter_44_clinic/"

    
    if first_step_candidate_result_directory[-1]!="/":
        first_step_candidate_result_directory+="/"
        
    if scond_step_candidate_result_directory[-1]!="/":
        scond_step_candidate_result_directory+="/"    
        
    #srcsplit= first_step_candidate_result_directory.split("/")
    directory_path = os.path.dirname(scond_step_candidate_result_directory)
    for_prallal_result_directory =scond_step_candidate_result_directory+"4_prallel_/"
    
    if not os.path.exists(scond_step_candidate_result_directory ):
        os.mkdir(scond_step_candidate_result_directory)
    if not os.path.exists(for_prallal_result_directory ):
        os.mkdir(for_prallal_result_directory)
#
    binary_files=[]

    for sample in os.listdir(first_step_candidate_result_directory):
        
        target_instances_path = first_step_candidate_result_directory + sample + "/ghidra_extract_result/"
        #if not os.path.exists(target_instances_path):
        #    continue
        if ".ipynb_checkpoints" in target_instances_path:
            continue
        target_instances = os.listdir(target_instances_path) 
        #shuffle(target_instances)
        
        for instance in target_instances:
            
            binaryFileName = target_instances_path + instance + "/" + instance  # +"/"+instance 
            
            ##if not os.path.exists(binaryFileName+'_ref2sink_cmdi.result'):
            ##    continue
            
            
            binary_files.append(binaryFileName)
            
            
    for  binaryFileName in binary_files:#  ["/home/jovyan/firmware_vr/Results/fd728c12a7a9ea264aef8d53e93357b06fa5eebafaccb7823bbccd1fe5f79e31_32973599/ghidra_extract_result/httpd/httpd"]:#binary_files:
            instance= os.path.basename(binaryFileName)
            sample= binaryFileName.split('/')[-4]
            
            if not os.path.exists(scond_step_candidate_result_directory + sample):
                os.mkdir(scond_step_candidate_result_directory + sample)
                
            
            check_pralled= for_prallal_result_directory+ sample+"_"+ f'{instance}.txt'
            # if  os.path.exists(check_pralled):
            #     continue
            # else :
            fff=open(check_pralled,'w') 
            fff.close()
            
            
            # if it doesnot have NVRAM operation ignore
            
            #if  not check_imported_library(binaryFileName):
            #    continue
            
            visited_file_name = os.path.join(scond_step_candidate_result_directory + sample, f'visited_{instance}.txt')
            visited_function_list=[]
            error_function_list=[]
            # To resume the investigation where the program stopped
            if os.path.exists(visited_file_name):
                my_visited_file=open(visited_file_name)
                for xline in my_visited_file:
                    temp_line_elements= xline.split(',')
                    if len(temp_line_elements) >0 and temp_line_elements[0].strip() not in visited_function_list :
                        visited_function_list.append(temp_line_elements[0].strip())
                ##visited_function_list=(my_visited_file.read()).split(" \n")
                my_visited_file.close()
                
                error_function_list=[]      
                '''
                my_error_file=open(os.path.join(scond_step_candidate_result_directory + sample, f'er ror_{instance}.txt'))
                
                for xline in my_error_file:
                    xx=xline.split(',')[1].split(":")[1].strip()
                    #print(xx)
                    if len(xx) >0 and xx in visited_function_list:
                        visited_function_list.remove(xx)
                my_error_file.close()
                '''
                    
                ##if "Done" in visited_function_list :
                ##    continue
            
            
            
            
            
            # Clear the dictionary
            Analyzed_Before.clear()
            # Force garbage collection
            #gc.collect()
            #print("HEEEEEEEEEERE")
            process = multiprocessing.Process(target=analyze_binary, args=(binaryFileName,visited_file_name,visited_function_list,scond_step_candidate_result_directory,))
            process.start()
            process.join()    
                
                


           
            
            
            






# Your foo function
def foo(project,memcpy_func_pred,handler):
    rd = project.analyses.ReachingDefinitions(subject=memcpy_func_pred,
                                              func_graph=memcpy_func_pred.graph,
                                              cc=memcpy_func_pred.calling_convention,
                                              dep_graph=dep_graph.DepGraph(), function_handler=handler
                                              )





#'''    
    
if __name__ == "__main__":
    # if len(sys.argv) != 3:
    #     print("Usage: python script.py <source_directory> <output_directory>")
    #     sys.exit(1)
    
    src_dir = r"" # r"julet_dataset/our_dataset_bad" #sys.argv[1]
    out_dir = r""  # r"julet_result" #sys.argv[2]    
    
    scnd_main(src_dir,out_dir)
    
    
#'''
